在下面的代码中,我尝试了三种方法来构建一个 csv 列表(从 1 到 5 的自然数序列)。
然后我使用\docsvlist
(from etoolbox
) 来包装列表的每个元素parentheses
。
所有这些尝试都失败了(请参阅代码)。为什么以及如何使它们按预期工作?
代碼:
\documentclass{article}
\usepackage{etoolbox}
\renewcommand{\do}[1]{(#1)}
% Method 1 to build a csv list
\def\aaa{1,2,3,4,5}
% Method 2 to build a csv list
\def\bbb{%
\newcount\foo
\foo=1
\loop
\ifnum \foo=5 5\else%
\the\foo,%
\advance \foo 1%
\repeat}
% Method 3 to build a csv list
\NewDocumentCommand\SequenceOfNaturalNumbers{mO{,}m}{%
%{#1-start number},[#2-dilimiter],{#3-end number}
\ifnum#1=#3 #3%
\else%
#1#2\SequenceOfNaturalNumbers{\number\numexpr #1+1}[#2]{#3}%
\fi%
}
\def\ccc{\SequenceOfNaturalNumbers{1}{5}}
\begin{document}
% Code 1:
\expandafter\docsvlist\expandafter{\aaa}\\
Q1: typeset 12345, not desired (1)(2)(3)(4)(5), why?
\bigskip
% Code 2:
bbb is : \bbb\\ %typeset 1,2,3,4,5 as expected
\docsvlist\bbb\\ %typeset 1,2,3,4,5, not desired (1)(2)(3)(4)(5)
\expandafter\docsvlist\expandafter{\bbb}\\ %This causes error
Q2: What's wrong with the above line of code?
\bigskip
% Code 3:
ccc is: \ccc\\ %typeset 1,2,3,4,5 as expected
\expandafter\docsvlist\expandafter{\ccc}\\
Q3: Why does the above line of code typeset 1,2,3,4,5, not desired (1)(2)(3)(4)(5)
\end{document}
答案1
该问题与宏无关:简单宏\docsvlist{a,b,c}
也会以同样的方式失败:
\documentclass{article}
\usepackage{etoolbox}
% Method 1 to build a csv list
\def\aaa{1,2,3,4,5}
% Method 2 to build a csv list
\def\bbb{%
\newcount\foo % would be better outside
\foo=1
\loop
\ifnum \foo=5 5\else%
\the\foo,%
\advance \foo 1 % space before % needed
\repeat}
% Method 3 to build a csv list
\NewDocumentCommand\SequenceOfNaturalNumbers{mO{,}m}{%
%{#1-start number},[#2-dilimiter],{#3-end number}
\ifnum#1=#3 #3%
\else%
#1#2\SequenceOfNaturalNumbers{\number\numexpr #1+1}[#2]{#3}%
\fi%
}
\def\ccc{\SequenceOfNaturalNumbers{1}{5}}
\begin{document}
%\renewcommand{\do}[1]{(#1)}
\docsvlist{a, b, c}
% Code 1:
\expandafter\docsvlist\expandafter{\aaa}\\
Q1: typeset 12345, not desired (1)(2)(3)(4)(5), why?
\bigskip
\end{document}
\do
是用于所有类型列表处理的核心 latex 命令,在任意位置(和 中\begin{document}
)重新定义,因此只有在处理之前立即设置时才能使用它\do
。取消注释 的定义\do
,您将看到两个列表都有效。
\expandafter\docsvlist\expandafter{\ccc}
是
\docsvlist{\SequenceOfNaturalNumbers{1}{5}}
这无法工作,\docsvlist
需要,
在参数中。
LaTeX 内置了用于映射逗号列表的函数,使这一过程变得更加容易
\documentclass{article}
% no package needed
\ExplSyntaxOn
\let\listmap\clist_map_inline:nn
\let\listvarmap\clist_map_inline:Nn
\cs_generate_variant:Nn \clist_map_inline:nn {e }
\let\listexpmap\clist_map_inline:en
\let\intmap\int_step_inline:nnnn
\let\addtolist\clist_put_right:Nn
\ExplSyntaxOff
\begin{document}
% map over a list
\listmap{aa,bb,cc}{(#1)}
% list in variable
\def\aaa{11,22,33}
% map over the variable's value
\listvarmap\aaa{(#1)}
% expand to a list, then map
\listexpmap{www,xx,\aaa,zz}{(#1)}
% Numeric loop
% {<start>} {<step>} {<end>} {<code>}
\intmap{5}{1}{10}{(#1)}
% you almost certainly don't need this, build list first
\edef\bbb{}
\intmap{8}{-2}{0}{\addtolist\bbb{item#1}}
\listvarmap\bbb{(#1)}
\end{document}