评估计算的逗号分隔列表中的每个元素

评估计算的逗号分隔列表中的每个元素

我有一个排列列表,我对其进行了排序,然后将其用作一些 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。您的代码主要存在两个问题:

  1. 您的\clist_use:Nn \l_my_clist调用缺少n-type 参数,该参数应该是要在项目之间使用的分隔符。例如,\clist_use:Nn \l_my_clist { , }可用于用逗号分隔项目。

  2. 为了\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}

相关内容