定义列表变量

定义列表变量

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}},在本回答的最后,你就会明白其中的原因。

\expandafterprimitive 在下一个参数之后扩展所给的参数。例如,如果有\def\foo{A}, \def\bar{B}\expandafter\foo\bar,它将首先变为\foo B,然后最终变为AB

类似地,我可以像这样解决上述问题:

noindent\expandafter\forcsvlist\expandafter\doforme\authors

如果我们看一下上面的递归表达式,第一个 expandafter 转到其第一个参数(\forcsvlist),跳过一段时间,然后尝试扩展它旁边的参数,在本例中是 again \expandafter。因此,第二个\expandafteragain 跳过\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}

相关内容