我需要一个计数器列表,但有一个特殊要求,即我事先不知道需要多少个计数器。我的第一个想法是使用一个长度可变的整数序列。正如 egreg 对
获取列表的第 n 个元素(使用 etoolbox,或不使用)
我想使用 xparse 包。如果有更简单的解决方案,请告诉我。
Egreg 的代码允许预定义列表、添加元素并读取第 n 个元素。但是,每次运行另一个命令时,我还想增加列表中的特定元素(增加 1)。但老实说,我对语法感到困惑。我尝试编写一个\setnthelement
具有可选参数(序列的标识符)和两个强制参数的函数:第一个参数应为要更改的列表索引,第二个参数应为指定索引处列表的新值。我使用以下代码
\documentclass[10pt]{scrartcl}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\newchangelist}{ m }
{
\seq_new:c { g_change_#1_seq }
}
\newchangelist{changelist}
\NewDocumentCommand{\addtochangelist}{ O{changelist} m }
{
\seq_gput_right:cn { g_change_#1_seq } { #2 }
}
\NewDocumentCommand{\getnthelement}{ O{changelist} m }
{
\seq_item:cn { g_change_#1_seq } { #2 }
}
\NewDocumentCommand{\setnthelement}{ O{changelist} m m } %not working
{
\cs_set:Npx{\seq_item:cn{g_change_#1_seq}{#2}{#3}}
}
\ExplSyntaxOff
\begin{document}
\addtochangelist{1}
\addtochangelist{0}
\addtochangelist{3}
\getnthelement{2}
%\setnthelement{1}{2}
%\setnthelement{2}{\getnthelement{2}+1}
%\getnthelement{2} %should now return 0+1=1)
\end{document}
如果任何一条\setnthelement
线路被激活,我就会收到类似的错误
插入了缺失的控制序列。\setnthelement{1}{2}
显然我的代码\setnthelement
是错误的。此外,我猜添加不会那么容易,所以也欢迎解决这个问题,但我可能可以自己解决这个问题。
您能帮助我并告诉我如何在特定索引处设置列表的值吗?
答案1
您不能仅通过寻址来修改序列中的元素。我认为您使用的工具不适合您的目的,属性列表可能更好。
无论如何,您可以这样做:重建序列。
为了进行算术运算,\getnthelement
必须使命令可扩展,并且需要\inteval
从包中获取。xfp
\documentclass[10pt]{scrartcl}
\usepackage{xparse,xfp}
\ExplSyntaxOn
\NewDocumentCommand{\newchangelist}{ m }
{
\seq_new:c { g_change_#1_seq }
}
\newchangelist{changelist}
\NewDocumentCommand{\addtochangelist}{ O{changelist} m }
{
\seq_gput_right:cn { g_change_#1_seq } { #2 }
}
\NewExpandableDocumentCommand{\getnthelement}{ O{changelist} m }
{
\seq_item:cn { g_change_#1_seq } { #2 }
}
\NewDocumentCommand{\setnthelement}{ O{changelist} m m }
{
\seq_clear:N \l_tmpa_tl
\int_step_inline:nnnn { 1 } { 1 } { #2 - 1 }
{
\seq_put_right:Nx \l_tmpa_tl { \seq_item:cn { g_change_#1_seq } { ##1 } }
}
\seq_put_right:Nx \l_tmpa_tl { #3 }
\int_step_inline:nnnn { #2 + 1 } { 1 } { \seq_count:c { g_change_#1_seq } }
{
\seq_put_right:Nx \l_tmpa_tl { \seq_item:cn { g_change_#1_seq } { ##1 } }
}
\seq_gset_eq:cN { g_change_#1_seq } \l_tmpa_tl
}
\ExplSyntaxOff
\begin{document}
\addtochangelist{1}
\addtochangelist{0}
\addtochangelist{3}
\getnthelement{2}
\setnthelement{1}{2}
\setnthelement{2}{\inteval{\getnthelement{2}+1}}
\getnthelement{2}
\end{document}
这将打印
0 1
可以添加检查是否有人试图超出序列的当前长度。
答案2
\documentclass{scrartcl}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand \newchangelist { m }
{
\seq_new:c { g_change_#1_seq }
}
\newchangelist{changelist}
\NewDocumentCommand \addtochangelist { O{changelist} m }
{
\seq_gput_right:cn { g_change_#1_seq } { #2 }
}
\NewDocumentCommand \getnthelement { O{changelist} m }
{
\seq_item:cn { g_change_#1_seq } { #2 }
}
\NewDocumentCommand \setnthelement { O{changelist} m m }
{
\seq_clear:N \l_tmpa_seq
\int_zero:N \l_tmpa_int
\seq_map_inline:Nn \l_tmpa_seq
{
\int_incr:N \l_tmpa_int
\int_compare:nNnTF { \l_tmpa_int } = { #2 }
{ \seq_put_right:Nn \l_tmpa_seq { #3 } }
{ \seq_put_right:Nn \l_tmpa_seq { ##1 } }
}
\seq_gset_eq:cN { g_change_#1_seq } \l_tmpa_seq
}
\ExplSyntaxOff
\begin{document}
\addtochangelist{1}
\addtochangelist{0}
\addtochangelist{3}
\getnthelement{2}
\setnthelement{1}{2}
\setnthelement{2}{\getnthelement{2}+1}
\getnthelement{2} %should now return 0+1=1)
\end{document}