迭代两个列表

迭代两个列表

我有两个逗号分隔的列表:

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}

相关内容