类似迭代器的命令,每次使用都会扩展到先前定义的列表中的一个项目

类似迭代器的命令,每次使用都会扩展到先前定义的列表中的一个项目

在 pdfLaTeX 中创建类似迭代器的宏(在函数编程意义上)的最简单方法是什么?

我想预定义一个元素列表(为了简化,我们可以假设它是纯字符串,例如 [C1, C2, C3] 或 [ad36bf, dea63f, 78f091]),并创建一个可以迭代此列表的宏,即每次使用它都会从列表中获取新元素。如果迭代器尝试访问列表中的更多元素,则应该出错,或者应该返回空内容。

例如,我希望

\deflist{A,B,C,D} % it doesn't need to use comma as separator

% ...

\el something \el xx \el

生产

A 某物 B xx C

我想使用这个宏来自动命名/编号用 TikZ/PGF 创建的图表中的节点......

答案1

这很简单expl3

\documentclass{article}

\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\deflist}{O{,}m}
 {
  \seq_set_split:Nnn \l_narebski_list_seq { #1 } { #2 }
 }

\NewDocumentCommand{\el}{}
 {
  \seq_item:Nn \l_narebski_list_seq { 1 }
  \seq_pop_left:NN \l_narebski_list_seq \l_narebski_waste_tl
 }

\seq_new:N \l_narebski_list_seq
\tl_new:N \l_narebski_waste_tl
\ExplSyntaxOff

\begin{document}

\deflist{A,B,C,D}

\el{} something \el{} xx \el{}

\deflist[-]{A-B}

\el{} something \el{} xx \el{}

\end{document}

在此处输入图片描述

输入被分成一个序列(分隔符周围的空格(可以作为 的可选参数进行更改\deflist)被修剪掉);每次调用时,\el都会传递第一个项目,然后将其从序列中弹出。

可以轻松添加对序列是否为空的检查:

\documentclass{article}

\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\deflist}{O{,}m}
 {
  \seq_set_split:Nnn \l_narebski_list_seq { #1 } { #2 }
 }

\NewDocumentCommand{\el}{}
 {
  \seq_pop_left:NN \l_narebski_list_seq \l_narebski_next_tl
  % if the sequence is empty, the token list will contain \q_no_value
  \quark_if_no_value:VTF \l_narebski_next_tl
   { $\langle$empty$\rangle$ }
   { \tl_use:N \l_narebski_next_tl }
 }

\seq_new:N \l_narebski_list_seq
\tl_new:N \l_narebski_next_tl
\cs_generate_variant:Nn \quark_if_no_value:nTF { V }
\ExplSyntaxOff

\begin{document}

\deflist{A,B,C,D}

\el{} something \el{} xx \el{}

\deflist[-]{A-B}

\el{} something \el{} xx \el{}

\end{document}

在此处输入图片描述

除了打印之外<empty>,还可以修改“真实”部分以发出警告或错误。

答案2

在这种情况下,项目之间用空格分隔,而不是用逗号分隔。如果您想要一个包含空格的项目,请将整个短语括在括号中,例如\deflist{A {B is the one} C D}

新的调用\deflist将重置计数器并重新构建列表。

\documentclass{article}
\usepackage{readarray}
\newcommand\deflist[1]{\setcounter{itcount}{0}\getargsC{#1}}
\newcounter{itcount}
\newcommand\el{\stepcounter{itcount}\ifnum\value{itcount}>\narg\else%
  \csname arg\romannumeral\value{itcount}\endcsname\ \fi}
\begin{document}
\deflist{A B C D} % it doesn't need to use comma as separator
% ...
\el something \el xx \el

\deflist{A {B is the one} C D}
\el something \el xx \el

\deflist{A B} % it doesn't need to use comma as separator
\el something \el xx \el
\end{document}

在此处输入图片描述

相关内容