使用 \foreach 与 \SplitArgument

使用 \foreach 与 \SplitArgument

为什么从 foreach 循环调用时 \test 命令不拆分参数?

\NewDocumentCommand{\test}{ >{\SplitArgument{3}{|}} m }{\printtest#1}
\NewDocumentCommand{\printtest}{mmmm}{
    (#1,#2)\quad s_{\IfValueT{#3}{#3}}\IfValueT{#4}{#4}}

\newcommand{\looptest}[1]{
   \foreach \n in {#1}{
       $\test{\n}$\\
    };

$\test{1|1}$\\       % this works
$\test{2|2|1}$\\     % this works
$\test{3|3|2|'}$\\   % this works
$\test{4|4|3|''}$\\  % this works

\looptest{1|2|1, 3|7|2, 6|7|3, 6|5, 9|5|3|''} % this does not

答案1

参数没有及时展开。每个 foreach 旋转参数仍然在括号对内。另外,不要在 foreach 参数内使用空格。这可能会导致模式不匹配。

\documentclass{article}
\usepackage{pgffor,xparse}

\NewDocumentCommand{\test}{ >{\SplitArgument{3}{|}} m }{\printtest#1}
\NewDocumentCommand{\printtest}{mmmm}{(#1,#2)\quad s_{\IfValueT{#3}{#3}}\IfValueT{#4}{#4}}
\newcommand{\looptest}[1]{\foreach\n in{#1}{$\expandafter\test\expandafter{\n}$\\}}

\begin{document}\noindent
$\test{1|1}$\\       % this works
$\test{2|2|1}$\\     % this works
$\test{3|3|2|'}$\\   % this works
$\test{4|4|3|''}$\\  % this works
\looptest{1|2|1,3|7|2,6|7|3,6|5,9|5|3|''} % this does not
\end{document}

在此处输入图片描述

答案2

这使用一种listofitems方法将输入解析为\looptest。介绍性\setsepchar{,}将解析字符设置为,。宏\readlist*\looplist{#1}将列表解析为\looplist[<index>]数组(同时忽略分隔符周围的空格,),然后使用\foreachitem循环按顺序访问该数组。但是,循环参数\n在被 消化之前必须展开一次\test

\documentclass{article}
\usepackage{pgffor,xparse,listofitems}

\NewDocumentCommand{\test}{ >{\SplitArgument{3}{|}} m }{\printtest#1}
\NewDocumentCommand{\printtest}{mmmm}{
    (#1,#2)\quad s_{\IfValueT{#3}{#3}}\IfValueT{#4}{#4}}

\newcommand{\looptest}[1]{%
   \setsepchar{,}%
   \readlist*\looplist{#1}%
   \foreachitem \n \in \looplist{%
       $\expandafter\test\expandafter{\n}$\\
    }
}

\begin{document}\noindent
$\test{1|1}$\\       % this works
$\test{2|2|1}$\\     % this works
$\test{3|3|2|'}$\\   % this works
$\test{4|4|3|''}$\\  % this works

\noindent\looptest{1|2|1, 3|7|2, 6|7|3, 6|5, 9|5|3|''} % this does not
\end{document}

在此处输入图片描述

这里有一种方法可以完全消除pgfforxparse,完全在内完成listofitems。请注意,不仅可以在列表逗号周围引入杂散空格,,还可以在|分隔符周围引入杂散空格,而不会产生任何不良影响。

\documentclass{article}
\usepackage{listofitems}
\makeatletter
\newcommand\test[1]{%
  \setsepchar{{|}}%
  \readlist*\testlist{#1}%
  \def\temp{\printtest}%
  \foreachitem\testitem\in\testlist{%
    \expandafter\g@addto@macro\expandafter\temp\expandafter{\expandafter{\testitem}}%
  }%
  \temp\relax\relax\relax%
}
\makeatother
\newcommand\printtest[4]{(#1,#2)\quad s_{#3}#4}
\newcommand{\looptest}[1]{%
   \setsepchar{,}%
   \readlist*\looplist{#1}%
   \foreachitem \n \in \looplist{%
       $\expandafter\test\expandafter{\n}$\\
    }%
}
\begin{document}\noindent
$\test{1|1}$\\       % this works
$\test{2|2|1}$\\     % this works
$\test{3|3|2|'}$\\   % this works
$\test{4|4|3|''}$\\  % this works

\noindent\looptest{1|2|1, 3|7|2, 6|7|3, 6|5, 9|5|3|''} % this does not
\end{document}

相关内容