我经常使用用 pgfmath 定义的列表,如果列表项之一是“33”,而不是“33”或“32”,就会遇到错误。下面是一个最简单的示例来重现错误。感谢任何能帮助我纠正这个问题的人。
\documentclass{minimal}
\usepackage{pgfmath}
\makeatletter
\def\pgfmathdeclarelist#1#2{%
\def\pgfmath@list@name{#1}%
\c@pgfmath@counta=0%
\pgfmath@declarelistlist#2{\pgfmath@stop}%
}
\def\pgfmath@declarelistlist#1{%
\ifx#1\pgfmath@stop%
\expandafter\edef\csname pgfmath@list@\pgfmath@list@name @length\endcsname{\the\c@pgfmath@counta}%
\else%
\advance\c@pgfmath@counta by1\relax%
\pgfutil@namedef{pgfmath@list@\pgfmath@list@name @\the\c@pgfmath@counta}{#1}%
\expandafter\pgfmath@declarelistlist%
\fi%
}
\makeatother
\begin{document}
\pgfmathdeclarelist{list}{{33}}
\end{document}
答案1
我猜你也有从这些列表中检索项目的命令,例如
\def\pgfmathlistitem#1#2{%
\ifnum \csname pgfmath@list@\pgfmath@list@name @length\endcsname<#2
\else
\csname pgfmath@list@#1@#2\endcsname
\fi
}
所以你可以这样做\pgfmathdeclarelist{list}{{3}{5}{6}{7}}
并\pgfmathlistitem{list}{2}
得到 5。
如您所见,如果某个项目以两个相等的标记开头,则该方法将失败,因为您正在执行
\ifx#1
如果#1
是,则33
测试返回 true。
你可以更简单地完成这件事。
\documentclass{article}
\ExplSyntaxOn
\NewDocumentCommand{\declarelist}{mm}
{
\seq_clear_new:c { l_laurent_list_#1_seq }
\tl_map_inline:nn { #2 }
{
\seq_put_right:cn { l_laurent_list_#1_seq } { ##1 }
}
}
\NewExpandableDocumentCommand{\listitem}{mm}
{
\int_compare:nTF { #2 == 0 }
{% return the list length
\seq_count:c { l_laurent_list_#1_seq }
}
{% return the item
\seq_item:cn { l_laurent_list_#1_seq } { #2 }
}
}
\ExplSyntaxOff
\begin{document}
\declarelist{list}{{33}{5}{6}{7}}
``\listitem{list}{1}'' should print 33
``\listitem{list}{0}'' should print 4
``\listitem{list}{-1}'' should print 7
\end{document}
使用否定论点时,将从末尾选择项目。
\csname
我使用序列,而不是使用多个标记expl3
。在声明时,给定的括号项被放入序列中,我们可以使用内置方法检索项。无需重新发明轮子。
可以添加检查以确保第二个参数\listitem
不超过列表长度,还可以添加检查以确保列表已被声明。