如何分别打印数组第一行和第二行元素的数量?

如何分别打印数组第一行和第二行元素的数量?

我已经分配了一个数组,我想设计一个带有 2 个值的命令(假设它名为\arraynum),分别打印数组第一行和第二行中的元素数量,例如

\documentclass{article}
\usepackage{tikz}

\makeatletter
\ExplSyntaxOn
\cs_set:Npn \MyArray #1 {
  \gdef\@MyArray{#1}
  \gdef\@Arraynum{\clist_count:n {#1}}
  \seq_set_split:Nnn \l_node_row_seq {;} {#1}
  \int_step_inline:nn{\seq_count:N \l_node_row_seq}
  {
    \seq_if_exist:cF {l_node_row_##1_seq}
    {
      \seq_new:c {l_node_row_##1_seq}
    }
    \exp_args:Ncx\seq_set_from_clist:Nn {l_node_row_##1_seq} {\seq_item:Nn \l_node_row_seq{##1}}
  }
}
\ExplSyntaxOff

\begin{document}

\MyArray{
    1,2,3,4,5,6,7;
    $\alpha$,$\beta$,$\gamma$,$\delta$,$\epsilon$
}

There are \@Arraynum{} elements in the array, 7 elements in the first line while 5 elements in the second line.

\end{document}

第一行有 7 个元素,因此命令\arraynum[1]{}应该\arraynum[1]{@MyArray}打印 7,而命令\arraynum[2]{@MyArray}应该打印 5。那么,我该如何设计这个命令呢?

而且,如你所见,数组中总共有 12 个元素,而第一行和第二行之间以符号 分隔;,但命令\clist_count:n {\@MyArray}无法识别分隔符号;,因此打印11时正确的数字是12。我该如何解决这些问题?

答案1

您可以更好地利用它expl3,以便您可以定义任意数量的数组并以统一的方式从中检索信息。

一般来说,不要\gdef与之混合expl3

请注意,下面的“步骤 2”命令是完全可扩展的。

步骤1。为阵列设置基础设施。

第2步。定义与这些数组一起使用的命令,例如“计数项目”或“检索一个项目”。

这是代码:数组被保存为 clist 序列。

\documentclass{article}

\ExplSyntaxOn

% step 1, set up arrays
\NewDocumentCommand{\definearray}{mm}
 {
  \seq_clear_new:c { l__axia_array_#1_seq }
  \seq_set_split:cnn { l__axia_array_#1_seq } { ; } { #2 }
 }

\cs_generate_variant:Nn \seq_set_split:Nnn { c }

% step 2, define commands to work with arrays
\NewExpandableDocumentCommand{\arraycount}{som}
 {
  \IfBooleanTF { #1 }
   {
    \seq_count:c { l__axia_array_#3_seq }
   }
   {
    \IfNoValueTF { #2 }
     {
      \axia_array_count_full:n { #3 }
     }
     {
      \axia_array_count_item:nn { #3 } { #2 }
     }
   }
 }

\cs_new:Nn \axia_array_count_full:n
 {
  \int_eval:n
   {
    0
    \seq_map_function:cN { l__axia_array_#1_seq } \__axia_array_count:n
   }
 }
\cs_new:Nn \__axia_array_count:n
 {
  + \clist_count:n { #1 }
 }

\cs_new:Nn \axia_array_count_item:nn
 {
  \clist_count:e { \seq_item:cn { l__axia_array_#1_seq } { #2 } }
 }

\NewExpandableDocumentCommand{\arrayitem}{mmm}
 {
  \clist_item:en { \seq_item:cn { l__axia_array_#1_seq } { #2 } } { #3 }
 }

\ExplSyntaxOff

\begin{document}

\definearray{MyArray}{
  1,2,3,4,5,6,7;
  $\alpha$,$\beta$,$\gamma$,$\delta$,$\epsilon$
}

There are \arraycount{MyArray} elements in the array, 
\arraycount[1]{MyArray} elements in the first line and
\arraycount[2]{MyArray} elements in the second line.

There are \arraycount*{MyArray} lines in the array.

The third item in the second line is \arrayitem{MyArray}{2}{3}.

\end{document}

您会看到\arraycount计算全长;如果您传递一个可选参数,您将获得相应行的长度;相反,\arraycount*{<name>}计算行数。

在此处输入图片描述

您可以通过以下方式测试完整的可扩展性

\edef\testA{\arraycount*{MyArray}}
\edef\testB{\arraycount{MyArray}}
\edef\testC{\arraycount[1]{MyArray}}

\texttt{\meaning\testA}\par
\texttt{\meaning\testB}\par
\texttt{\meaning\testC}

在此处输入图片描述

您可以在同一文档中

\definearray{Another}{aaa,bbb,ccc;ddd,eee;fff,ggg,hhh;iiii}

\arraycount{Another}

\arraycount*{Another}

\arraycount[1]{Another}--%
\arraycount[2]{Another}--%
\arraycount[3]{Another}--%
\arraycount[4]{Another}

你会得到

在此处输入图片描述

答案2

使用listofitems, 代替 expl3:

\documentclass{article}
\usepackage{listofitems}
\newtoks\zz
\newcommand\addtozz[1]{\global\zz\expandafter{\the\zz#1}}
\newcommand\xaddtozz[1]{\expandafter\addtozz\expandafter{#1}}
\newcommand\xxaddtozz[1]{\expandafter\xaddtozz\expandafter{#1}}
\setsepchar{;/,}
\newcommand\TotalElements{\zz{}%
  \foreachitem\z\in\MyArray[]{%
    \ifnum\zcnt=1 \else\addtozz{+}\fi
    \xxaddtozz{\listlen\MyArray[\zcnt]}%
  }%
  \the\numexpr\the\zz\relax
}    
\begin{document}
\readlist*\MyArray{
    1,2,3,4,5,6,7;
    $\alpha$,$\beta$,$\gamma$,$\delta$,$\epsilon$
}

There are \TotalElements{} elements in the array, \listlen\MyArray[1] elements 
in the first line while \listlen\MyArray[2] elements in the second line.
\end{document}

在此处输入图片描述

由于计数器是全局的,因此实际上使用它们比使用标记列表更容易,可以进行计数\TotalElements

\documentclass{article}
\usepackage{listofitems}
\newcounter{zz}
\setsepchar{;/,}
\newcommand\TotalElements{\setcounter{zz}{0}%
  \foreachitem\z\in\MyArray[]{%
    \addtocounter{zz}{\listlen\MyArray[\zcnt]}%
  }%
  \thezz
}    
\begin{document}
\readlist*\MyArray{
    1,2,3,4,5,6,7;
    $\alpha$,$\beta$,$\gamma$,$\delta$,$\epsilon$
}

There are \TotalElements{} elements in the array, \listlen\MyArray[1] elements 
in the first line while \listlen\MyArray[2] elements in the second line.
\end{document}

相关内容