Print the number of elements in the first and second rows of an array respectively

countexpl3latex3

I've assigned an array and I want to design a command (Assume it's named \arraynum) with 2 values to print the number of elements in the first and second rows of an array respectively, for example

\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}

There are 7 elements in the first line, so the command \arraynum[1]{}the command \arraynum[1]{@MyArray} should print 7 while the command \arraynum[2]{@MyArray} should print 5. So, how can I design this command?

Whats's more, as you can see, there are 12 elements in the array in total, while the first line and the second line were separated by the symbol ;, but the command \clist_count:n {\@MyArray} couldn't recognize the separate symbol ; so it print 11 while the correct number is 12. How can I solve these problems?

Best Answer

You can make better use of expl3 so you can define as many arrays as you want and retrieve information from them in a uniform way.

As a general rule, don't mix \gdef with expl3.

Note that the “step 2” commands below are fully expandable.

Step 1. Set up an infrastructure for arrays.

Step 2. Define commands to work with these arrays, for instance “count items” or “retrieve one item”.

Here's the code: the array is saved as a sequence of clists.

\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}

You see that \arraycount computes the full length; if you pass an optional argument you get the length of the corresponding row; instead, \arraycount*{<name>} computes the number of lines.

enter image description here

You can test full expandability by doing

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

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

enter image description here

You can do, in the same document,

\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}

and you'll get

enter image description here

Related Question