3

I stored a list of strings (command strings) in an array following the answer here: https://tex.stackexchange.com/a/215571/61517 . Now I wanted to access them randomly, and therefore I added a random counter (by using lcq) to it:

\storedata{general}{{a}{b}{c}}
\reinitrand[counter=GenCounter, last=3]
\getdata[\value{GenCounter}]{general}

My problem is now: I want to expand the general-array by adding further commands to it, but then I also have to modify the last-value for the \reinitrand[]-function in order to access all elements. Is there a possibility to add a counter to the \storedata-macro in order to see the current length of the array, and set the reinit-macro accordingly?
My final goal is to access all elements in the array randomly, regardless of the number of the elements in the array, without having the possible problem of an out-of-bounds-exception resulting in nothing. Furthermore I don't want to change the last-value of the random initialization everytime I change the amount of commands in the array, it should update itself.

Extention 2: My code looks like (taken from the answer noted above):

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\storedata}{mm}
  {
   \bcp_store_data:nn { #1 } { #2 }
  }

\NewDocumentCommand{\appenddata}{mm}
 {
  \bcp_append_data:nn { #1 } { #2 }
 }

\DeclareExpandableDocumentCommand{\getdata}{O{1}m}
 {
  \bcp_get_data:nn { #1 } { #2 }
 }

\cs_new_protected:Npn \bcp_store_data:nn #1 #2
 {
  % create the sequence if it doesn't exist or clear it if it exists
  \seq_if_exist:cTF { l_bcp_data_#1_seq }
   { \seq_new:c { l_bcp_data_#1_seq } }
   { \seq_clear:c { l_bcp_data_#1_seq } }
  % append the items
  \__bcp_append_data:nn { #1 } { #2 }
 }

\cs_new_protected:Npn \bcp_append_data:nn #1 #2
 {
  % create the sequence if it doesn't exist, do nothing if it exists
  \seq_if_exist:cF { l_bcp_data_#1_seq }
   { \seq_new:c { l_bcp_data_#1_seq } }
  % append the items
  \__bcp_append_data:nn { #1 } { #2 }
 }

\cs_new_protected:Npn \__bcp_append_data:nn #1 #2
 {
  % append items one at a time
  \tl_map_inline:nn { #2 }
   {
    \seq_put_right:cn { l_bcp_data_#1_seq } { ##1 }
   }
 }

\cs_new:Npn \bcp_get_data:nn #1 #2
 {
  % retrieve the requested item
  \seq_item:cn { l_bcp_data_#2_seq } { #1 }
 }
\ExplSyntaxOff

\begin{document}

\storedata{mydata}{{one}{two}}
\appenddata{mydata}{{three}{four}}

\getdata[1]{mydata}

\getdata[2]{mydata}

\getdata[3]{mydata}

\getdata[4]{mydata}

\printlength{mydata}% How can I define this function?
\end{document}

How do I get the length of mydata, i.e. the result of \printlength?

5
  • 1
    It would help to know what is your end goal.
    – Alenanno
    Feb 20, 2016 at 16:30
  • @Alenanno: Added, please notify me if my aim is not clear.
    – arc_lupus
    Feb 20, 2016 at 16:33
  • 1
    I deleted my answer. That's why I said it's helpful to know what you want to do, your code, etc.
    – Alenanno
    Feb 20, 2016 at 18:32
  • Your array is of seq type. Just use \seq_count:N to obtain the number of elements. Feb 21, 2016 at 9:31
  • @HenriMenke: How can I include that as a callable macro?
    – arc_lupus
    Feb 21, 2016 at 11:30

1 Answer 1

3

Using \seq_count:N in a wrapper command will provide the number of elements in the sequence.

Here the variant \seq_count:c must be used since the sequence name is generated and not known before in a \l_...seq like command name.

As can be seen, the \printlength macro is expandable.

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\storedata}{mm}
  {
   \bcp_store_data:nn { #1 } { #2 }
  }

\NewDocumentCommand{\appenddata}{mm}
 {
  \bcp_append_data:nn { #1 } { #2 }
 }

\DeclareExpandableDocumentCommand{\getdata}{O{1}m}
 {
  \bcp_get_data:nn { #1 } { #2 }
 }

\cs_new_protected:Npn \bcp_store_data:nn #1 #2
 {
  % create the sequence if it doesn't exist or clear it if it exists
  \seq_if_exist:cTF { l_bcp_data_#1_seq }
   { \seq_new:c { l_bcp_data_#1_seq } }
   { \seq_clear:c { l_bcp_data_#1_seq } }
  % append the items
  \__bcp_append_data:nn { #1 } { #2 }
 }

\cs_new_protected:Npn \bcp_append_data:nn #1 #2
 {
  % create the sequence if it doesn't exist, do nothing if it exists
  \seq_if_exist:cF { l_bcp_data_#1_seq }
   { \seq_new:c { l_bcp_data_#1_seq } }
  % append the items
  \__bcp_append_data:nn { #1 } { #2 }
 }

\cs_new_protected:Npn \__bcp_append_data:nn #1 #2
 {
  % append items one at a time
  \tl_map_inline:nn { #2 }
   {
    \seq_put_right:cn { l_bcp_data_#1_seq } { ##1 }
   }
 }

\cs_new:Npn \bcp_get_data:nn #1 #2
 {
  % retrieve the requested item
  \seq_item:cn { l_bcp_data_#2_seq } { #1 }
 }

\newcommand{\printlength}[1]{%
  \seq_count:c { l_bcp_data_#1_seq }
}
\ExplSyntaxOff

\begin{document}

\storedata{mydata}{{one}{two}}
\appenddata{mydata}{{three}{four}}

\getdata[1]{mydata}

\getdata[2]{mydata}

\getdata[3]{mydata}

\getdata[4]{mydata}

\ifnum\printlength{mydata} > 1\relax
Hooray% How can I define this function?
\else
Nope!
\fi
\end{document}

enter image description here

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .