![对两个逗号分隔列表上的压缩迭代映射任意操作](https://linux22.com/image/417904/%E5%AF%B9%E4%B8%A4%E4%B8%AA%E9%80%97%E5%8F%B7%E5%88%86%E9%9A%94%E5%88%97%E8%A1%A8%E4%B8%8A%E7%9A%84%E5%8E%8B%E7%BC%A9%E8%BF%AD%E4%BB%A3%E6%98%A0%E5%B0%84%E4%BB%BB%E6%84%8F%E6%93%8D%E4%BD%9C.png)
我正在尝试结合但没有成功这些 二方法变成了一种强大的东西,它允许我 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}