使用 \SplitArgument 函数将以标记分隔的值的数组作为单个参数传递

使用 \SplitArgument 函数将以标记分隔的值的数组作为单个参数传递

在我从事线性代数和矩阵的工作中,我受到 LaTeX2 及其最多可传递给 9 个参数的\newcommand限制。虽然 LaTeX3 对 也施加了同样的限制,但\NewDocumentCommand我(非常兴奋地)注意到该xparse包提供了许多可以解决此限制的参数处理器。特别是\SplitArgument似乎正好提供了我需要的东西。遗憾的是,我无法从阅读文档中提取足够的信息来interface3编写将使用 提取的数据并将它们放在我需要的位置的层\SplitArgument。我希望下面的代码是不言自明的;它可以编译但由于显而易见的原因,它可以编译\myNinePerm但不编译mynPerm。我相信我的问题的答案不仅对我有很大的帮助,而且可以作为一个受欢迎的实际示例为所有 TeX 和 LaTeX3 新手提供帮助。

%document name: LaTeX3_xparse2.tex
%RN 16/3/2012
%COMMENTS: 
%   OBJECTIVE: Want to populate an nxn matrix by passing its elements separated by semicolons
%   as a single argument rather than by passing them individually (which poses the restriction 
%   to 3 x 3 matrices since LaTeX3 imposes the same maximum number of arguments, 9, as does 
%   LaTeX2). LaTeX3 and one or other of the argument processors in xparse, for instance 
%   \SplitArgument will to the job, but once again, due to the lack of at least one concrete 
%   example, I cannot get the syntax right, especially for the internal function! 
%   APPROACH: 
%   (1) Have a simple function, call it \myNinePerm which displays a permutation of a 9-set 
%   as a 2 x 9 matrix with the top row showing the elements of the set in natural order and 
%   row 2 allowing the user to plug in their images under the mapping as individual arguments 
%   by passing the values as arguments(the LaTeX2 approach);
%   (2) rewrite this same function by passing a single argument which contains the values 
%   separated by some token, for example a semi-colon. The restriction to nine elements is no 
%   longer relevant, but is maintained in order to avoid clouding the issue.
%==============================================================================================
\documentclass{article}
%\usepackage{expl3}
\usepackage{amsmath,xparse} 

\ExplSyntaxOn 
\NewDocumentCommand{\myNinePerm}{ m m m m m m m m m } 
{ 
    {\begin{pmatrix} 
    1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 & 9 \\
    #1 & #2 & #3 & #4 & #5 & #6 & #7 & #8 & #9 
    \end{pmatrix}} 
}
\ExplSyntaxOff 

\ExplSyntaxOn 
\NewDocumentCommand{\mynPerm}{ m } 
{ > { \SplitArgument { 8 } { ; } } m }
% assuming that the argument now contains nine values, how do I move these values to
% occupy the second row in the matrix below?
    { 
    {\begin{pmatrix} 
    1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 & 9 \\
%   <val 1>&<val 2>&<val 3>&<val 4>&<val 5>&<val 6>&<val 7>&<val 8>&<val 9> 
    \end{pmatrix}} 
}
\ExplSyntaxOff 

\begin{document}
$\myNinePerm{9}{8}{7}{6}{5}{4}{3}{2}{1}$\\
$\mynPerm{{9;8;7;6;5;4;3;2;1}}$\\
\end{document}

答案1

\SplitArgument\SplitList适用于非常基本的列表处理。当人们只需在项目之间插入一些内容时,事情会稍微复杂一些。

我提出了一个更简单的版本,它也可以处理任意数量的元素

\documentclass{article}
\usepackage{amsmath}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\perm}{ O{,} m } { \perm_build:nn { #1 } { #2 } }

%%% Here's the "real" code
\tl_new:N \l_perm_toprow_tl
\tl_new:N \l_perm_bottomrow_tl
\seq_new:N \l_perm_permutation_seq
\int_new:N \l_perm_numberofcols_int
\cs_new:Npn \perm_build:nn #1 #2
  {
   \group_begin:
   \cs_set_eq:cN {c@MaxMatrixCols} \l_perm_numberofcols_int
   \seq_set_split:Nnn \l_perm_permutation_seq { #1 } { #2 }
   \int_set:Nn \l_perm_numberofcols_int { 1 }
   \tl_set:Nn \l_perm_toprow_tl { 1 }
   \seq_pop_left:NN \l_perm_permutation_seq \l_perm_bottomrow_tl
   \seq_map_inline:Nn \l_perm_permutation_seq
     {
      \int_incr:N \l_perm_numberofcols_int
      \tl_put_right:Nx \l_perm_toprow_tl { & \int_to_arabic:n { \l_perm_numberofcols_int } }
      \tl_put_right:Nn \l_perm_bottomrow_tl { & ##1 }
     }
   \begin{pmatrix}
   \tl_use:N \l_perm_toprow_tl \\
   \tl_use:N \l_perm_bottomrow_tl
   \end{pmatrix}
   \group_end:
  }
\ExplSyntaxOff
\begin{document}
$\perm{1,2,3,4,5,6,7,8,9}$

$\perm[;]{9;8;7;6;5;4;3;2;1;10;11;12}$
\end{document}

它使用一个序列在分离第一列后进行通常的映射。在映射的每个步骤中,我们将适当的元素添加到顶行和底行。

最后,我们设置了一个pmatrix,但使用了一个技巧,即让\c@MaxMatrixCols\l_perm_numberofcols_int,这样当请求的列数超过默认值 10 时,LaTeX 就不会发出声音。

怎么运行的

我们首先\perm用一个可选值(默认值,)和一个强制值来定义我们要构建的矩阵的第二行。这只是将控制权转移到“内部”版本\perm_build:nn

下一步是声明变量:两个用于存储行的标记列表、一个用于艰苦工作的序列和一个将执行两项服务的整数。

在一个组中,我们让 LaTeX 相信这是我们的整数变量(参见的\c@MaxMatrixCols文档),然后我们使用可选参数来拆分强制参数并将信息片段存储在序列中。amsmathMaxMatrixCols\perm

然后我们在序列上开始递归,将整数变量初始化为 1,并将顶行包含“1”(这是必要的,以避免行分隔符&太多)。因此,我们分离序列中最左边的元素(\seq_pop_left:NN)初始化底行(感谢 Bruno Le Floch 提供的这个巧妙技巧)。

我们\seq_map_inline:Nn进行递归:对于序列的每个元素,我们将 前面的整数变量的值(刚刚增加的)添加到顶行&;类似地,我们将其添加到底行&,后面跟着序列中的当前项(用 表示##1)。

最后,我们设置矩阵并关闭组,因此保持MaxMatrixCols不变,并且在工作期间不受列数的限制。

通过使用函数,可以将其推广到在顶行中具有任意元素序列\seq_mapthread_function:NNN

答案2

我想尝试回答您的问题并提供一种方法。

首先一个小提示:提供的命令xparse不需要用ExplSyntaxOn...括起来。ExplSyntaxOff

在上述方法中,函数\mynPerm定义有一个可选参数和一个强制参数。语法如下:

\mynPerm[<separator>]{<list>}

默认分隔符为;。输入参数不受限制。矩阵的第一列由强制输入的参数数量计算得出。

输入以下几行

\mynPerm{9;8;7;6;5;4;3;2;1}

\mynPerm{13;15;15,65;19}

\mynPerm[,]{13;15;15,65;19}

结果为:

\documentclass{article}
%\usepackage{expl3}
\usepackage{amsmath,xparse} 

\NewDocumentCommand{\myNinePerm}{ m m m m m m m m m } 
{%
    \ensuremath{%
      \begin{pmatrix}% 
        1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 & 9 \\
      #1 & #2 & #3 & #4 & #5 & #6 & #7 & #8 & #9 
      \end{pmatrix}%
     }% 
}

%
\ExplSyntaxOn 
\seq_new:N \l_perm_store_seq
\seq_new:N \l_perm_tmpa_seq
\cs_generate_variant:Nn \seq_set_eq:NN {Nn}
\tl_new:N \l_perm_first_column_tl
\tl_new:N \l_perm_second_column_tl

\NewDocumentCommand \mynPerm { O{;} m } 
 {
  \seq_clear:N \l_perm_store_seq
  \seq_set_split:Nnn \l_perm_store_seq { #1 } { #2 } 
  \seq_mynPerm_set_first_column:N \l_perm_store_seq
  \seq_mynPerm_set_second_column:N \l_perm_store_seq
  \seq_mynPerm_output_matrix:NN \l_perm_first_column_tl \l_perm_second_column_tl
 }

\cs_new:Npn \seq_mynPerm_set_first_column:N #1 
 {
  \seq_set_eq:NN \l_perm_tmpa_seq #1
  \int_set_eq:NN \l_tmpa_int \c_two
  \tl_set:Nx \l_perm_first_column_tl { 1 & }
  \int_while_do:nNnn { \l_tmpa_int } < { \seq_length:N \l_perm_tmpa_seq }
   { 
    \tl_put_right:NV \l_perm_first_column_tl { \l_tmpa_int & }
    \int_incr:N \l_tmpa_int
   }
   \tl_put_right:NV \l_perm_first_column_tl { \l_tmpa_int }
%   \tl_to_str:N \l_perm_first_column_tl
 }

\cs_new:Npn \seq_mynPerm_set_second_column:N #1 
 {
   \seq_set_eq:NN \l_perm_tmpa_seq #1
   \tl_clear:N \l_perm_second_column_tl 
   \seq_map_inline:Nn \l_perm_tmpa_seq
    {
     \tl_put_right:Nn \l_perm_second_column_tl { ##1 & }
    }
   \tl_reverse:N \l_perm_second_column_tl
   \tl_remove_once:Nn \l_perm_second_column_tl { & }
   \tl_reverse:N \l_perm_second_column_tl
%   \tl_to_str:N \l_perm_second_column_tl
 }

\cs_new:Npn \seq_mynPerm_output_matrix:NN #1 #2
 {
   \group_begin:
    \tl_set_eq:NN \l_tmpa_tl #1
    \tl_set_eq:NN \l_tmpb_tl #2
    \int_set:cn {c@MaxMatrixCols} { \tl_length:N \l_tmpa_tl }
    \ensuremath{%
      \begin{pmatrix}% 
        \tl_use:N \l_tmpa_tl     \\
        \tl_use:N \l_tmpb_tl
      \end{pmatrix}%
     }%
   \group_end: 
 }
\ExplSyntaxOff 

\begin{document}
\myNinePerm{9}{8}{7}{6}{5}{4}{3}{2}{1}


\mynPerm{9;8;7;6;5;4;3;2;1}

\mynPerm{13;15;15,65;19}

\mynPerm[,]{13;15;15,65;19}
\end{document}

相关内容