我有一个排列列表,我对其进行了排序,然后将其用作一些 TikZ 图形的阴影。
\documentclass{article}
\usepackage{expl3, tikz}
\ExplSyntaxOn
\clist_new:N \l_my_clist
\NewDocumentCommand{\sorted}{m}
{
\clist_set:Nx \l_my_clist {#1}
\clist_sort:Nn \l_my_clist
{ \int_compare:nTF { ##1 > ##2 } { \sort_return_swapped: } { \sort_return_same: } }
\clist_use:Nn \l_my_clist
}
\ExplSyntaxOff
\newcommand{\myperm}{1,8,15,4,6,5,12,10,13,2,11,14,7,16,3,9}
\newcommand{\mysorted}{\sorted{\myperm}}
\begin{document}
\foreach \x [evaluate=\x as \shade using \x*6] in \myperm{
\x~\shade\\
}\\
\foreach \x [evaluate=\x as \shade using \x*6] in \mysorted{
\x~\shade
}
\end{document}
第二个循环的评估无法编译,并出现错误:
\LaTeX3 error:
A sequence was misused.
我猜想排序列表的元素不是整数。如何将它们展开?
答案1
欢迎使用 TeX.SE。您的代码主要存在两个问题:
您的
\clist_use:Nn \l_my_clist
调用缺少n
-type 参数,该参数应该是要在项目之间使用的分隔符。例如,\clist_use:Nn \l_my_clist { , }
可用于用逗号分隔项目。为了
\foreach \x ... in \mysorted
工作,\mysorted
必须扩张到逗号分隔的列表。但是,您的\mysorted
宏会扩展为\sorted{\myperm}
,并且您的\sorted
宏包含几个命令,这些命令不可扩展(\clist_set:Nx
和\clist_sort:Nn
)。此外,您的\sorted
宏是\protected
因为它是用 定义的\NewDocumentCommand
,因此它不会在仅扩展的上下文中扩展,而这通常是此类解析所必需的。因此,代码无法以这种方式工作。
我建议做一个简单的修改:将\mysorted
宏重命名为,\mysort
并给它两个参数。第二个参数被解释为\sorted
宏的唯一参数。第一个参数是一个控制序列标记,用于\mysort
存储排序操作的结果。因此,指定控制序列标记的第一级扩展将\mysort
完成工作后以逗号分隔的列表。
(此外,由于这里没有风险,我们可以使用已经定义的\l_tmpa_clist
变量来代替——顺便说一下,\l_my_clist
它可能应该被命名为:私有变量。)\l__my_clist
\documentclass{article}
\usepackage{xparse} % only necessary if LaTeX format older than 2020-10-01
\usepackage{pgffor}
\usepackage{multicol} % for a nicer layout
\ExplSyntaxOn
\NewDocumentCommand \mysort { m m }
{
\clist_set:Nx \l_tmpa_clist {#2}
\clist_sort:Nn \l_tmpa_clist
{
\int_compare:nTF { ##1 > ##2 }
{ \sort_return_swapped: }
{ \sort_return_same: }
}
\tl_set:Nx #1 { \clist_use:Nn \l_tmpa_clist { , } }
}
\ExplSyntaxOff
\newcommand{\myperm}{1,8,15,4,6,5,12,10,13,2,11,14,7,16,3,9}
% The first argument specifies where to store the result.
\mysort{\mysorted}{\myperm}
\begin{document}
\begin{multicols}{2}
\foreach \x [evaluate=\x as \shade using \x*6] in \myperm {
\x~\shade\par
}%
\columnbreak
\bigskip
\foreach \x [evaluate=\x as \shade using \x*6] in \mysorted {
\x~\shade\par
}
\end{multicols}
\end{document}
正如评论中提到的并如下所示,也可以这样做:
- 使用
seq
变量而不是clist
; - 使用
\int_compare:nNnTF {##1} > {##2}
而不是\int_compare:nTF { ##1 > ##2 }
进行排序操作(这可以使排序更快)。
\documentclass{article}
\usepackage{xparse} % only necessary if LaTeX format older than 2020-10-01
\usepackage{pgffor}
\usepackage{multicol} % for a nicer layout
\ExplSyntaxOn
\cs_generate_variant:Nn \seq_set_from_clist:Nn { Nx }
\NewDocumentCommand \mysort { m m }
{
\seq_set_from_clist:Nx \l_tmpa_seq {#2}
\seq_sort:Nn \l_tmpa_seq
{
\int_compare:nNnTF {##1} > {##2}
{ \sort_return_swapped: }
{ \sort_return_same: }
}
\tl_set:Nx #1 { \seq_use:Nn \l_tmpa_seq { , } }
}
\ExplSyntaxOff
\newcommand{\myperm}{1,8,15,4,6,5,12,10,13,2,11,14,7,16,3,9}
% The first argument specifies where to store the result.
\mysort{\mysorted}{\myperm}
\begin{document}
\begin{multicols}{2}
\foreach \x [evaluate=\x as \shade using \x*6] in \myperm {
\x~\shade\par
}%
\columnbreak
\bigskip
\foreach \x [evaluate=\x as \shade using \x*6] in \mysorted {
\x~\shade\par
}
\end{multicols}
\end{document}