4

I am having a problem of using the command of \forlistloop of etoolbox

unlike the way of typical C program where

int a[5]
for ( i = 0; i <5; i++)
{
    a[i]
}

one could access i I am not sure how to access the individual elements of the list using the command.

I see that \forlistloop<handler><list> is the basic sequence that is given.

I tried the following and get errors of undefined sequence.

\def\myrowlist{}
\forcsvlist{\listadd\myrowlist}{r,\theta,z}

$   \newcounter{itemcount}
    %\begin{itemize}
        \forlistloop{\stepcounter{itemcount}\itemRaone}{\myrowlist}
        \itemRaone
    %\item Total: \number\value{itemcount} items
    %\end{itemize}
$

My expectation is that I should be able to extract r, \theta and z separately each time.

7
  • Instead of piling up questions after questions you should consider accepting answers to your questions first, showing that you appreciate users' efforts to help you. And please don't post only fragments
    – user31729
    Jul 22, 2015 at 9:39
  • Hi Christian,very sorry. Since I am new to this forum I am not sure how to accept an answer. I am thankful for whosoever is replying. But if there is a way to show do it in a formal way do tell me. I am actually not very aware of the rules of the internet and the forum and using it for the first time in my life. Jul 22, 2015 at 9:57
  • lists by etoolbox are not random access lists, i.e. you can't extract at once list element like a in C - vector
    – user31729
    Jul 22, 2015 at 15:28
  • I think Christian means voting "up" or "down" answers by clicking on the "up" or "down" icons near the top-left of each answer. You are not obligated to vote, of course, but the system is designed so that highly "up-voted" answers will appear near the top of the answer list relative to less highly up-voted answers. The person who asks the question can also "accept" an answer that the questioner thinks best (or adequately or completely or superbly) answers the question. Contributing to this site in this way is helpful to others who need help but may not be able to distinguish between answers.
    – jon
    Jul 23, 2015 at 2:40
  • @jon: Just to add: I did not mean upvoting/accepting my answer. I answered hours after writing my first comment
    – user31729
    Jul 23, 2015 at 4:56

3 Answers 3

4

Try the routines \grabitem{number} to get the item from the list. It's not failsafe, of course.

In general, it's better to use wrapper commands instead of doing stuff like \forcsvlist{\stepcounter...}{..} directly.

\documentclass{article}

\usepackage{etoolbox}


\listadd\myrowlist{}

\newcounter{itemcount}
\newcommand{\additem}[2][\myrowlist]{%
  \listadd{#1}{#2}%
  \stepcounter{itemcount}%
}%

\newcommand{\addtolist}[2][\myrowlist]{%
  \setcounter{itemcount}{0}
  \let #1\relax
  \listgadd #1{}%
  \forcsvlist{\additem[#1]}{#2}%
}

\makeatletter
\newcounter{temp@@count}

\newcommand{\getitem}[2]{%
  \stepcounter{temp@@count}%
    \ifnumequal{\value{temp@@count}}{#1}{%
      \ensuremath{#2}%
      \listbreak
    }{}
}%

\newcommand{\grabitem}[2][\myrowlist]{%
  \setcounter{temp@@count}{0}
  \ifnumgreater{#2}{\value{itemcount}}{%
    \GenericError{Error}{Number #2 for grabbing item too large}{There are only \number\value{itemcount} items}{Check your code!}
  }{% All is ok.
    \forlistloop{\getitem{#2}}{#1}%
  }
}

\makeatother

\newcommand{\showlist}[1]{%
$#1$

}%



\begin{document}

\addtolist{r,\theta,z,\Gamma,\Delta}

\forlistloop{\showlist}{\myrowlist} 

\grabitem{1}

\grabitem{5}


\begin{itemize}
  \forcsvlist{\item \grabitem[\myrowlist]}{1,3,5,4,5,2}
\end{itemize}



\end{document}
2
  • I realise I am late in commenting this, but doesn't this make it so that your commands are built to manipulate any list at all, changing at the same time the value of itemcount, which is only related to the number of items in the specific \myrowlist?
    – sgf
    Dec 23, 2016 at 22:07
  • @thisismynamenow: I never claimed that it would be valid in all cases.
    – user31729
    Dec 25, 2016 at 15:17
2

If you are willing to switch from etoolbox to the more powerful expl3 programming environment, you could do like this:

\documentclass{article}

\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\newlist}{m}
 {
  \seq_new:c { g_sumanta_lists_#1_seq }
 }
\newlist{myrow} % default

\NewDocumentCommand{\additems}{O{myrow} m}
 {
  \clist_map_inline:nn { #2 }
   {
    \seq_gput_right:cn { g_sumanta_lists_#1_seq } { ##1 }
   }
 }

\NewDocumentCommand{\getitem}{O{myrow} m O{\use:n}}
 {
  \int_compare:nTF { #2 > \seq_count:c { g_sumanta_lists_#1_seq } }
   {
    NO ITEM
   }
   {
    #3 { \seq_item:cn { g_sumanta_lists_#1_seq } { #2 } }
   }
 }

\NewDocumentCommand{\uselist}{O{\use:n}m}
 {
  \seq_map_inline:cn { g_sumanta_lists_#2_seq } { #1 { ##1 } }
 }
\ExplSyntaxOff

\newcommand{\makeitem}[1]{\item $#1$}

\begin{document}

\additems{r,\theta,z,\Gamma}
\additems{\Delta}

\getitem{1}

\getitem{2}[\ensuremath]

\getitem{99}

\begin{itemize}
\uselist[\makeitem]{myrow}
\end{itemize}

\newlist{foo}

\additems[foo]{a,b,c}

\begin{enumerate}
\uselist[\makeitem]{foo}
\end{enumerate}


\end{document}

The optional argument to \additems is a list name (default myrow), the mandatory one is a comma separated list of items.

With \getitem you obtain the item whose number is specified by the mandatory argument; the first optional argument is a list name, the trailing optional argument is a one parameter macro that wraps the item (default is just producing the item). In case the number exceeds the available items, NOITEM is printed; this could be turned into an error message.

The \uselist command takes as optional argument a one parameter macro that should wrap the item. The default is just producing the item.

enter image description here

1
  • A typical egreg - solution: Stealing from other's ;-)
    – user31729
    Jul 22, 2015 at 19:13
2

For iterating over an elementary list of items, you can use an array-like structure/interface (similar to what one would expect in programming languages like C) provided by arrayjobx:

enter image description here

\documentclass{article}
\usepackage{multido,arrayjobx}

\newarray\myrowlist\readarray{myrowlist}{r & \theta & z}

\begin{document}

\newcommand{\itemdelim}{\renewcommand{\itemdelim}{,\,}}% http://tex.stackexchange.com/a/89187/5764
$\multido{\i=1+1}{3}{\itemdelim\myrowlist(\i)}$

\end{document}

Elements within the array is specified using \readarray{<array>} where <array> is an &-delimited sequence.

multido has an easy enough interface to iterate over some \integer sequence.

You must log in to answer this question.

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