我有两个逗号分隔的列表:
ListA(a,b,c,d,e,f,g)
和
ListB(name1,name2,name3,name4,name5)
我想同时遍历这两个列表,例如:
loop
readvalue from list A
readvalue from list B
create new variable aname1{}
repeat
如果迭代到达任一列表的末尾,则迭代应该停止。
答案1
遍历所有元素的解决方案:
\documentclass{article}
\usepackage{pstricks}
\psforeach{\A}{a,b,c,d,e,f,g}{%
\psforeach{\B}{name1,name2,name3,name4,name5}{%
\expandafter\xdef\csname\A\B\endcsname{Def: \A,\B}}}
\begin{document}
\csname aname1\endcsname
\csname ename4\endcsname
\end{document}
确保逗号未激活,否则将无法正常工作。例如,以下操作会失败。此外,请确保列表中没有虚假空格。
\begingroup
\catcode`\,=13
\def\x{\endgroup
\psforeach{\A}{a,b,c,d,e,f,g}{%
\psforeach{\B}{name1,name2,name3,name4,name5}{%
\expandafter\xdef\csname\A\B\endcsname{Def: \A,\B}%
}%
}%
}
\x
答案2
您可以使用以下代码将函数映射到两个逗号分隔的列表上。它还允许您将两个逗号分隔的列表“压缩”在一起。所有这些都是可扩展的,例如适合在语句中使用\write
等。或者更确切地说,如果您映射的函数本身可扩展,它就是可扩展的。请参阅代码末尾的适合您情况的示例。
\documentclass{minimal}
\usepackage{expl3}
\ExplSyntaxOn
% Spaces are now ignored, and `_` and `:` can be used in macro names.
%
% `\tl_if_either_empty_ii:nn` tests whether either one of two token
% lists is empty.
%
\prg_new_conditional:Npnn \tl_if_either_empty_ii:nn #1 #2 {p,T,F,TF} {
\tl_if_empty:nTF {#1} {\prg_return_true:} {
\tl_if_empty:nTF {#2} {\prg_return_true:} {\prg_return_false:}
}
}
% Function to zip two clist together, e.g.,
% {1,2,3,4,5} {aa,bb,cc,d} -> {1}{aa}, {2}{bb}, {3}{cc}, {4}{d}
% It stops when reaching the end of any of the two lists. For people who
% care: it is `f`-expandable.
%
\cs_new:Npn \clist_zip_ii:nn #1 #2 {
\clist_zip_ii_aux:nw {} #1, \q_mark, #2, \q_mark.
}
\cs_new:Npn \clist_zip_ii_aux:nw #1 #2, #3 \q_mark, #4, #5 \q_mark. {
\tl_if_either_empty_ii:nnTF {#3} {#5} {
#1 {#2}{#4}
}{
\clist_zip_ii_aux:nw {#1 {#2}{#4},} #3 \q_mark, #5 \q_mark.
}
}
\cs_generate_variant:Nn \clist_zip_ii:nn {VV}
% To map a function `#3` of two arguments onto the zipped result,
% we do something similar, essentially replacing commas by `#1` in
% the output.
\cs_new:Npn \clist_map_zip_ii:nnN #1 #2 #3 {
\clist_map_zip_ii_aux:Nnw #3 {} #1, \q_mark, #2, \q_mark.
}
\cs_new:Npn \clist_map_zip_ii_aux:Nnw #1 #2 #3, #4 \q_mark, #5, #6 \q_mark. {
\tl_if_either_empty_ii:nnTF {#4} {#6} {
#2 #1{#3}{#5}
}{
\clist_map_zip_ii_aux:Nnw #1 {#2 #1{#3}{#5}} #4 \q_mark, #6 \q_mark.
}
}
\cs_generate_variant:Nn \clist_map_zip_ii:nnN {VV}
% ======================= Your comma separated lists ==================
% All those `g` mean `global`.
\clist_new:N \g_my_first_clist
\clist_new:N \g_my_second_clist
\clist_gput_right:Nn \g_my_first_clist {a,b,c,d,e,f}
\clist_gput_right:Nn \g_my_second_clist {1,2,3,4,5}
\cs_new:Npn \my_create_variable:nn #1 #2 {
\iow_term:n {Creating~variable~``#1 name #2''} % Message to the terminal
\tl_new:c {#1 name #2}
}
\clist_map_zip_ii:VVN \g_my_first_clist
\g_my_second_clist
\my_create_variable:nn
% Restore the usual behaviour of space, colon and underscore.
\ExplSyntaxOff
\begin{document}
\end{document}
答案3
如果您不介意全局分配和交错列表,您可以使用\foreach
以下宏pgffor
:
\documentclass{article}
\usepackage{pgffor}
\begin{document}
\foreach \name/\value in {namea/a,nameb/b,namec/c} {%
\global\expandafter\def\csname\name\expandafter\endcsname\expandafter{\value}%
}
% Test:
\show\namea \show\nameb \show\namec
\end{document}
否则,您需要编写自己的循环,从每个列表中删除一个值。只需查看\@for
循环在 中是如何定义的latex.ltx
。
答案4
这是使用简单迭代的另一种解决方案。很抱歉,代码不太干净。
\documentclass{article}
\makeatletter
\long\def\getfirst@#1,#2\@@#3{\def#3{#1}}
\long\def\getfirst#1#2{%
\def\temp{#2}%
\expandafter\getfirst@\temp,\@nil\@@#1}
\def\@nil@{\@nil}
\long\def\getrest@#1,#2\@@#3{\def\temp{#2}%
\ifx\@nil@\temp
\let#3\undefined
\else
\expandafter\getrest@@\temp#3
\fi}
\long\def\getrest@@#1,\@nil#2{\def#2{#1}}
\long\def\getrest#1#2{%
\def\temp{#2}%
\expandafter\getrest@\temp,\@nil\@@#1}
\long\def\split#1#2#3{%
\def\temp{#3}%
\expandafter\getfirst@\temp,\@nil\@@#1
\def\temp{#3}%
\expandafter\getrest@\temp,\@nil\@@#2}
\begin{document}
% your list
\def\listA{a,b,c,d,e,f}
\def\listB{X,Y,Z,W}
\newif\ifloop
\def\testloop{%
\ifx\listA\undefined \loopfalse \fi
\ifx\listB\undefined \loopfalse \fi
\ifloop}
\looptrue
\loop
% extract list
\expandafter\split\expandafter\firstofA\expandafter\restofA\expandafter{\listA}
\expandafter\split\expandafter\firstofB\expandafter\restofB\expandafter{\listB}
% show progress
{\tt
\meaning\firstofA \qquad \meaning\restofA\qquad
\meaning\firstofB \qquad \meaning\restofB\par}%
% do definition
\expandafter\edef \csname TT\firstofA\endcsname {\firstofB}%
% iteration
\let\listA\restofA
\let\listB\restofB
\testloop\repeat
result:\\
\verb=\TTa= is \TTa\\
\verb=\TTb= is \TTb\\
\verb=\TTc= is \TTc\\
\verb=\TTd= is \TTd
\end{document}