我etoolbox
专门用于列表处理\forcsvlist
。
当将逗号分隔的列表直接传递给 时\forcsvlist
,它能够解析列表中的每个项目。但是,如果我在其他地方定义列表变量,则\forcsvlist
无法区分列表中的每个项目,并将其作为一个整体参数。
例如:
\newcommand\doforme[1]{#1 \\}
\forcsvlist\doforme{a,b,c}
上面的代码完美地在每个项目的末尾添加了换行符。但是下面的代码不起作用
\newcommand\doforme[1]{#1 \\}
\def\@authors{a,b,c}
\forcsvlist\doforme{\@authors}
这使我认为一定还有其他方法来定义可以解释的列表\forcsvlist
。
答案1
使用变量形式的问题在于其早期扩展会将整体a,b,c
视为一个实体。所谓一个实体,我指的是列表中唯一的单个元素。
为了解决这个问题,首先我们需要在这里使用双括号。所以{a,b,c}
变成了{{a,b,c}}
,在本回答的最后,你就会明白其中的原因。
\expandafter
primitive 在下一个参数之后扩展所给的参数。例如,如果有\def\foo{A}, \def\bar{B}
和\expandafter\foo\bar
,它将首先变为\foo B
,然后最终变为AB
。
类似地,我可以像这样解决上述问题:
noindent\expandafter\forcsvlist\expandafter\doforme\authors
如果我们看一下上面的递归表达式,第一个 expandafter 转到其第一个参数(\forcsvlist),跳过一段时间,然后尝试扩展它旁边的参数,在本例中是 again \expandafter
。因此,第二个\expandafter
again 跳过\doforme
一段时间,然后扩展\authors.
\authors
当前为{{a,b,c}}
。扩展后它变成{a,b,c}
。所以最终的表达式现在变成
\noident\forcsvlist\doforme{a,b,c}
这相当于像问题中的第一个案例那样传递参数,从而产生相同的结果。
答案2
该包etoolbox
定义了一个特殊命令来处理内部列表:\forlistloop
。这些列表使用特殊字符作为内部列表分隔符。因此您必须使用\listadd
(或类似命令 - 请参阅etoolbox
文档) 将项目添加到此类列表中。
\documentclass{article}
\usepackage{etoolbox}
\begin{document}
\newcommand\doforme[1]{#1 \\}
\forcsvlist{\listadd\authors}{a,b,c}
\noindent\forlistloop\doforme{\authors}
\end{document}