对两个逗号分隔列表上的压缩迭代映射任意操作

对两个逗号分隔列表上的压缩迭代映射任意操作

我正在尝试结合但没有成功这些 方法变成了一种强大的东西,它允许我 zip 迭代两个列表并做任意酷的事情:

\zip{a,b,c}{1,2,3}{#1-#2 }

将扩展为

a-1 b-2 c-3 

那么为何不

\zip[#1/#2][#3::#4]
    {a/A,b/B,c/C}
    {1::I,2::II,3::III}
    {Grand #1 is #2 but grand #3 is #4.\\}

将扩展为

Grand a is A but grand 1 is I.\\
Grand b is B but grand 2 is II.\\
Grand c is C but grand 3 is III.\\

到目前为止,我最好的尝试是在之后附加此代码@BrunoLeFloch 的解决方案

\NewDocumentCommand{\zip}{mmm}
 {
  \cs_set:Npn \__egreg_apply_aux:nn ##1 \q_stop { #3 }
  \clist_map_zip_ii:VVN #1 #2 \__egreg_apply_aux:nn
 }

没有运气,也许秘诀接口3发现我还没有纯洁到足以揭开他们的秘密:'(

答案1

用第一种方式定义\zip非常简单:

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand{\zip}{mm +m}
 {
  \seq_set_from_clist:Nn \l__iagolito_zip_a_seq { #1 }
  \seq_set_from_clist:Nn \l__iagolito_zip_b_seq { #2 }
  \cs_set:Nn \__iagolito_zip:nn { #3 }
  \seq_mapthread_function:NNN \l__iagolito_zip_a_seq \l__iagolito_zip_b_seq \__iagolito_zip:nn
 }

\seq_new:N \l__iagolito_zip_a_seq
\seq_new:N \l__iagolito_zip_b_seq

\ExplSyntaxOff

\begin{document}

\zip{a,b,c}{1,2,3}{#1-#2 }

\end{document}

您可以查看此印刷品

a-1 b-2 c-3

如果两个列表的元素数量不同,则循环在任一列表结束时结束。


更复杂的功能也可以实现。请注意,如果需要复杂的处理,两个可选参数必须同时出现。

这个想法是填充另一个序列,其中两个列表合并,然后可以应用辅助宏。

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand{\zip}{oomm +m}
 {
  \IfNoValueTF { #1 }
   { \iagolito_zip_simple:nnn { #3 } { #4 } { #5 } }
   { \iagolito_zip_full:nnnnn { #1 } { #2 } { #3 } { #4 } { #5 } }
 }

\seq_new:N \l__iagolito_zip_a_seq
\seq_new:N \l__iagolito_zip_b_seq
\seq_new:N \l__iagolito_zip_c_seq

\cs_new_protected:Nn \iagolito_zip_simple:nnn
 {
  \seq_set_from_clist:Nn \l__iagolito_zip_a_seq { #1 }
  \seq_set_from_clist:Nn \l__iagolito_zip_b_seq { #2 }
  \cs_set:Nn \__iagolito_zip:nn { #3 }
  \seq_mapthread_function:NNN \l__iagolito_zip_a_seq \l__iagolito_zip_b_seq \__iagolito_zip:nn
 }

\cs_new_protected:Nn \iagolito_zip_full:nnnnn
 {
  \seq_set_from_clist:Nn \l__iagolito_zip_a_seq { #3 }
  \seq_set_from_clist:Nn \l__iagolito_zip_b_seq { #4 }
  \seq_clear:N \l__iagolito_zip_c_seq
  \cs_set:Npn \__iagolito_zip_process:w #1 \q_stop #2 \q_stop { #5 }
  \seq_mapthread_function:NNN \l__iagolito_zip_a_seq \l__iagolito_zip_b_seq \__iagolito_merge:nn
  \seq_map_inline:Nn \l__iagolito_zip_c_seq { ##1 }
 }

\cs_new_protected:Nn \__iagolito_merge:nn
 {
  \seq_put_right:Nn \l__iagolito_zip_c_seq { \__iagolito_zip_process:w #1 \q_stop #2 \q_stop }
 }

\ExplSyntaxOff

\begin{document}

\zip{a,b,c}{1,2,3}{#1-#2 }

\zip[#1/#2][#3::#4]
    {a/A,b/B,c/C}
    {1::I,2::II,3::III}
    {Grand #1 is #2 but grand #3 is #4.\par}

\end{document}

在此处输入图片描述

如果要将宏扩展传递给列表,请进行一步扩展。

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand{\zip}{oomm +m}
 {
  \IfNoValueTF { #1 }
   { \iagolito_zip_simple:oon { #3 } { #4 } { #5 } }
   { \iagolito_zip_full:nnoon { #1 } { #2 } { #3 } { #4 } { #5 } }
 }

\seq_new:N \l__iagolito_zip_a_seq
\seq_new:N \l__iagolito_zip_b_seq
\seq_new:N \l__iagolito_zip_c_seq

\cs_new_protected:Nn \iagolito_zip_simple:nnn
 {
  \seq_set_from_clist:Nn \l__iagolito_zip_a_seq { #1 }
  \seq_set_from_clist:Nn \l__iagolito_zip_b_seq { #2 }
  \cs_set:Nn \__iagolito_zip:nn { #3 }
  \seq_mapthread_function:NNN \l__iagolito_zip_a_seq \l__iagolito_zip_b_seq \__iagolito_zip:nn
 }
\cs_generate_variant:Nn \iagolito_zip_simple:nnn { oo }

\cs_new_protected:Nn \iagolito_zip_full:nnnnn
 {
  \seq_set_from_clist:Nn \l__iagolito_zip_a_seq { #3 }
  \seq_set_from_clist:Nn \l__iagolito_zip_b_seq { #4 }
  \seq_clear:N \l__iagolito_zip_c_seq
  \cs_set:Npn \__iagolito_zip_process:w #1 \q_stop #2 \q_stop { #5 }
  \seq_mapthread_function:NNN \l__iagolito_zip_a_seq \l__iagolito_zip_b_seq \__iagolito_merge:nn
  \seq_map_inline:Nn \l__iagolito_zip_c_seq { ##1 }
 }
\cs_generate_variant:Nn \iagolito_zip_full:nnnnn { nnoo }

\cs_new_protected:Nn \__iagolito_merge:nn
 {
  \seq_put_right:Nn \l__iagolito_zip_c_seq { \__iagolito_zip_process:w #1 \q_stop #2 \q_stop }
 }

\ExplSyntaxOff

\newcommand{\listA}{a,b,c}
\newcommand{\listB}{1,2,3}
\newcommand{\listC}{a/A,b/B,c/C}
\newcommand{\listD}{1::I,2::II,3::III}

\begin{document}

\zip{a,b,c}{1,2,3}{#1-#2 }
\zip{\listA}{1,2,3}{#1-#2 }
\zip{a,b,c}{\listB}{#1-#2 }
\zip{\listA}{\listB}{#1-#2 }

\zip[#1/#2][#3::#4]
    {a/A,b/B,c/C}
    {1::I,2::II,3::III}
    {Grand #1 is #2 but grand #3 is #4.\par}

\zip[#1/#2][#3::#4]
    {\listC}
    {1::I,2::II,3::III}
    {Grand #1 is #2 but grand #3 is #4.\par}

\zip[#1/#2][#3::#4]
    {a/A,b/B,c/C}
    {\listD}
    {Grand #1 is #2 but grand #3 is #4.\par}

\zip[#1/#2][#3::#4]
    {\listC}
    {\listD}
    {Grand #1 is #2 but grand #3 is #4.\par}

\end{document}

输出与之前相同,只是每个实例重复四次。

答案2

编辑以提供对 OP 提出的所有场景的完整答案。只要始终有两个列表可以合并,就可以完成这项工作listofitems

可选子参数分隔符可以是多标记;但它们不能包括/|,但如果这是一个问题,请告诉我。也许可以做出一些调整。

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{listofitems}
\def\zipaux{}
\newcommand\zip[1][]{%
  \def\tmpA{#1}%
  \zipB%
}
\newcommand\zipB[1][]{%
  \expandafter\zipC\expandafter{\tmpA}{#1}%
}
\newcommand\zipC[5]{%
  \ifx\relax#1\relax
    \setsepchar{,}%
    \readlist*\argA{#3}%
    \ifx\relax#2\relax
      \renewcommand\zipaux[2]{#5}%
      \setsepchar{,}
    \else
      \renewcommand\zipaux[3]{#5}%
      \setsepchar{,/#2}
    \fi
  \else
    \setsepchar{,/#1}%
    \readlist*\argA{#3}%
    \ifx\relax#2\relax
      \renewcommand\zipaux[3]{#5}%
      \setsepchar{,}
    \else
      \renewcommand\zipaux[4]{#5}%
      \setsepchar{,/#2}
    \fi
  \fi%
  \readlist*\argB{#4}%
  \foreachitem\z\in\argB{%
    \ifx\relax#1\relax
      \ifx\relax#2\relax
        \zipaux{\argA[\zcnt]}{\argB[\zcnt]}%
      \else
        \zipaux{\argA[\zcnt]}{\argB[\zcnt,1]}{\argB[\zcnt,2]}%
      \fi
    \else
      \ifx\relax#2\relax
        \zipaux{\argA[\zcnt,1]}{\argA[\zcnt,2]}{\argB[\zcnt]}%
      \else
        \zipaux{\argA[\zcnt,1]}{\argA[\zcnt,2]}
               {\argB[\zcnt,1]}{\argB[\zcnt,2]}%
      \fi
    \fi
  }%
}
\begin{document}
\zip{a,b,c}{1,2,3}{#1-#2 }

\zip[?]{a?A,b?B,c?C}{1,2,3}{(#1*#2)-#3 }

\zip[?][::]{a?A,b?B,c?C}{1::X,2::Y,3::Z}{(#1*#2)-#3/#4 }

\zip[][::]{a,b,c}{1::X,2::Y,3::Z}{(#1-#2)/#3 }
\end{document}

在此处输入图片描述

答案3

具有两个参数的简单情况

在此处输入图片描述

\documentclass{article}

\begin{document}

\def\zip#1#2#3{%
\def\z##1##2{#3}%
\xzip#1,\relax#2,\relax}
\def\xzip#1,#2\relax#3,#4\relax{%
\z{#1}{#3}%
\if\relax\detokenize{#2}\relax
\expandafter\zzgobble
\fi
\xzip#2\relax#4\relax
}

\def\zzgobble#1\relax#2\relax{}


\zip{a,b,c}{1,2,3}{#1-#2 }
\end{document}

相关内容