序言中是否有一个可以起作用的 \foreach 函数?

序言中是否有一个可以起作用的 \foreach 函数?

Tikz/PGF 有一个非常有用的 \foreach 实现,它允许构造

\foreach \x / \y in {1/a,2/b,3/c,4/d} {\x is a lot like \y}

您可以在其中迭代一对列表。此命令仅在 tikz 环境中有效,因此在序言中尤其无效,我想使用它来定义大量看起来非常相似的宏,例如\newcommand{\task\x}{\function\y};(实际上我在 tikz 中定义新形状,每个形状都有五十行或更多代码,因此重复几百次确实不切实际)。

tex 中是否有可以轻松执行类似操作的函数?我知道我可以使用 ForArray 函数或嵌套 for 循环来组合此功能,但结果似乎比较不雅致,我希望这里有人可能有一个干净的方法(或使用数组或循环的干净实现)。

答案1

您可以在序言中将\xdef(全局扩展定义)与\csname ... \endcsnameinside一起使用\foreach。它在序言中起作用,但将内容包含在需要全局定义的组中。循环“变量”(宏)必须在定义之前/期间扩展,否则宏将只包含\y而不是其当前内容。

这里有一个如何定义宏的例子,比如\mymacroa\mymacrob等等,它将包含一个\dostuff获取\y内容的调用。

\documentclass{article}

\usepackage{pgffor}

\foreach \x/\y in {a/1,b/2,c/3,d/4} {
    \expandafter\xdef\csname mymacro\x\endcsname{%
        \noexpand\dostuff{\y}%
    }%
}

\newcommand{\dostuff}[1]{\texttt{(#1)}}

\begin{document}

\mymacroa

\mymacrob

\mymacroc

\mymacrod

\end{document}

如果您想做一些不同的事情,比如定义 PGF 形状,那么最好只是累积所需的宏调用并扩展循环变量,然后执行累加器。

以下代码将添加\dostuff{<x>}{<y>}\mycommands在任何组外循环后执行的。然后它包含\dostuff {a}{1}\dostuff {b}{2}\dostuff {c}{3}\dostuff {d}{4}

\documentclass{article}

\usepackage{pgf}
\usepackage{pgffor}
\usepackage{etoolbox}

\newcommand{\mycommands}{}

\newcommand{\dostuff}[2]{%
    \pgfdeclareshape{#1}{%
        \anchor{#2}{...}%
    }%
}

\foreach \x/\y in {a/1,b/2,c/3,d/4} {%
    \xappto{\mycommands}{\noexpand\dostuff{\x}{\y}}%
}
%\show\mycommands
\mycommands

\begin{document}

\end{document}

答案2

pgffor确实可以在外部环境中工作tikzpicture,尽管对于某些应用程序来说它不够强大。

一个问题是,你错误地使用了\newcommand。你不能改用\newcommand{\task\x}{\function\y}、使用\@namedef{task\x}{\function\y}或类似的东西。

另一个问题是由于pgffor。它是以组为单位执行的,使用它定义新宏时必须扩展变量。

\x示例解决方案,您必须小心控制和的扩展\y

\documentclass{article}
\usepackage{pgffor}
\foreach \x/\y in {a/1,b/2,c/3} {
  \expandafter\xdef\csname cmd\x\endcsname{number \y}
}
\begin{document}
\cmda, \cmdb, \cmdc
\end{document}

另一种解决方案是使用etoolbox,这是首选:

\documentclass{article}
\usepackage{etoolbox}
\def\dodo#1/#2{\csdef{cmd#1}{number #2}}
\def\do#1{\dodo#1}
\docsvlist{a/1,b/2,c/3}
\begin{document}
\cmda, \cmdb, \cmdc
% we obtain: number 1, number 2, number 3
\end{document}

答案3

使用 catoptions 包,辅助功能就不再必要,您还可以使用任意列表分隔符。此外,在生效\dodo之前,列表的每个元素都会先去掉多余的前导空格和尾随空格。\do

\documentclass{article}
\usepackage{catoptions}[2011/10/22]

\begin{document}

\def\do#1/#2{\csndef*{cmd#1}{number #2}}
\dofunclist{a/1, b/2, c/3}

%\dofunclist[;]{a/1; b/2; c/3}
\cmda, \cmdb, \cmdc

\end{document}

相关内容