我在网上找到了某种列表,并让它按预期工作。命令“addtoaliste”正在向列表“aliste”添加一个参数。它由 newcommands 定义,因此我无法让它在 enumerate 等环境中工作,因为任何更改都只能在本地完成。
我将尝试更改我实施的列表,使其与全局定义 (gdef) 配合使用。但首先是我的“命令代码”:
\documentclass{scrartcl}
\usepackage{ifthen}
\newcommand{\aliste}[1]{\empty}
\def\zaliste#1\relax{\def\aliste##1{#1}}
\newcommand{\addtoaliste}[1]{%
\ifthenelse{\equal{\aliste{}}{}}{
\expandafter\zaliste\aliste{##1}#1\relax}
{\expandafter\zaliste\aliste{##1},#1\relax}
}
\begin{document}
Value: \aliste{}\\ %Returns empty list
\addtoaliste{1}
Value: \aliste{} %Returns 1
\begin{enumerate}
\item First Point.
\addtoaliste{2}
\end{enumerate}
Value: \aliste{} %shall return 1,2, but still returns 1
\end{document}
我尝试了一些更改并得到以下结果,但它仍然没有按预期工作:
\documentclass{scrartcl}
\usepackage{ifthen}
\gdef\aliste#1{}
\gdef\zaliste#1{\relax{\gdef\aliste##1{#1}}}
\gdef\addtoaliste#1{%
\ifthenelse{\equal{\aliste{}}{}}{
\expandafter\zaliste\aliste{##1}#1\relax}
{\expandafter\zaliste\aliste{##1},#1\relax}
}
\begin{document}
Value: \aliste{}\\ %Returns empty list
\addtoaliste{1}
Value: \aliste{}\\ %Returns 1
\begin{enumerate}
\item First Point.
\addtoaliste{2}
\end{enumerate}
Value: \aliste{}
\end{document}
答案1
使用\gdef
不会真正改变代码:\gdef
意味着“全局定义”,但宏内的代码应该进行全局定义。所以
\def\zaliste#1\relax{\gdef\aliste##1{#1}}
将是解决方案,只要宏开始起作用,但事实并非如此。
问题在于
\def\zaliste#1{\relax{\gdef\aliste##1{#1}}}
一副额外的牙套会毁掉一切:应该是
\def\zaliste#1\relax{\gdef\aliste##1{#1}}
因此参数被 界定\relax
。事实上
\documentclass{scrartcl}
\usepackage{ifthen}
\def\aliste#1{}
\def\zaliste#1\relax{\gdef\aliste##1{#1}}
\def\addtoaliste#1{%
\ifthenelse{\equal{\aliste{}}{}}{%
\expandafter\zaliste\aliste{##1}#1\relax}%
{\expandafter\zaliste\aliste{##1},#1\relax}%
}
\begin{document}
Value: \aliste{} %Returns empty list
\addtoaliste{1}
Value: \aliste{} %Returns 1
\begin{enumerate}
\item First Point.
\addtoaliste{2}
\end{enumerate}
Value: \aliste{}
\end{document}
生产
我不确定你为什么\aliste
要用参数来定义,这只会让事情变得复杂。在下面,我还改为\gdef
以便\xdef
扩展值,以防你想使用类似的东西\addtoalist{\arabic{enumi}}
\documentclass{scrartcl}
\usepackage{ifthen}
\def\aliste{}
\def\zaliste#1\relax{\xdef\aliste{#1}} % \xdef for full expansion
\def\addtoaliste#1{%
\ifthenelse{\equal{\aliste}{}}{%
\expandafter\zaliste\aliste#1\relax
}{\expandafter\zaliste\aliste,#1\relax
}%
}
\begin{document}
Value: \aliste %Returns empty list
\addtoaliste{1}
Value: \aliste %Returns 1
\begin{enumerate}
\item First Point.
\addtoaliste{2}
\end{enumerate}
Value: \aliste
\end{document}
将产生完全相同的结果。
我建议采用一种不同的方法,它可以支持您想要的任意数量的列表。
\documentclass{scrartcl}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\startlist}{m}
{
\clist_clear_new:c { g_wuagh_list_#1_clist }
}
\NewDocumentCommand{\addtolist}{mm}
{
% add the item
\clist_gput_right:cx { g_wuagh_list_#1_clist } { #2 }
}
\NewExpandableDocumentCommand{\uselist}{om}
{
\IfNoValueTF { #1 }
{
\clist_use:cn { g_wuagh_list_#2_clist } { , }
}
{
\clist_item:cn { g_wuagh_list_#2_clist } { #1 }
}
}
\ExplSyntaxOff
\startlist{a}
\begin{document}
Value: \uselist{a} %Returns empty list
\addtolist{a}{A}
Value: \uselist{a} %Returns 1
\begin{enumerate}
\item First Point.\addtolist{a}{\arabic{enumi}}
\item Second Point.\addtolist{a}{\arabic{enumi}}
\end{enumerate}
Value: \uselist{a}
Item: \uselist[1]{a} % returns A
Item: \uselist[2]{a} % returns 1
\end{document}
如您所见,您还可以通过索引访问列表项。
答案2
您可以使用etoolbox
为您管理列表(添加和处理/打印):
\documentclass{article}
\usepackage{etoolbox}
% https://tex.stackexchange.com/a/89187/5764
% \printlist[<separator>]{<list>}
\newcommand{\printlist}[2][,]{%
\def\itemdelim{\def\itemdelim{#1}}% Item delimiter delayed by one cycle
\renewcommand*{\do}[1]{\itemdelim##1}% How each item is processed
\dolistcsloop{#2}}% Process CSV list
\newcommand{\addtoaliste}{\listcsgadd{aliste}}
\begin{document}
Value: \printlist{aliste} % Returns empty list
\addtoaliste{1}
Value: \printlist{aliste} % Returns 1
\begin{enumerate}
\item First Point.
\addtoaliste{2}
\end{enumerate}
Value: \printlist{aliste} % Returns 1,2
\end{document}
列表打印使用狡猾的 (La)TeX 技巧。