2.7.3 ⁑Iteration With etoolbox's Internal Lists
The previous section looked at iterating over
a comma-separated list, but it may be that you need to first construct
a list before iterating over it. This can be done efficiently via
etoolbox's internal lists. These don't use a comma as
a separator so it's useful for lists where items may potentially
contain commas. For example, suppose I want to make a list called, say,
\mylist
, then I first need to define an empty list:
\newcommand*{\mylist}{}
An item can be added to the list using:
where ⟨list cs⟩ is the command used to store the list
(\mylist
in the above example) and ⟨item⟩ is the item
to add to the list. Note that the ⟨item⟩ doesn't get expanded and
a blank item won't be added to the list. For example:
If the item needs to be expanded before being added to the list, you can use:
As with \listadd
, a blank item won't be added to the list.
For example:
There are also similar commands where you supply the name of the list macro without the leading backslash:
(unexpanded item) and
(expanded item). For example:
\renewcommand*{\Name}{Zebra} \listcseadd{mylist}{\Name} \listcsadd{mylist}{Arara}
These commands all use local assignments, so they're limited to the current scope. There are analogous commands that use global assignments:
(global version of \listadd
)
(global version of \listeadd
)
(global version of \listcsadd
) and
(global version of \listcseadd
).
You can test if an item is in a list using:
(No expansion is performed on ⟨item⟩.) For example:
If you want to test the expansion of an item, you can use:
For example:
There are also analogous commands where the list control sequence name (without the leading backslash) is supplied:
for the non-expanded version and
for the item expansion version.
Once you've added all your items to the list, you can iterate over the list using:
where ⟨list cs⟩ is the control sequence storing the list
(\mylist
in the above examples). If you prefer to supply
the control sequence name without the leading backslash, you can
use:
Both these commands use \do
{
⟨item⟩}
at each iteration, in
the same way as for \docsvlist
described
earlier.
For example:
\newcommand*{mylist}{}% \listadd{\mylist}{Parrot}% \listadd{\mylist}{Canary}% \listadd{\mylist}{Zebra}% \listadd{\mylist}{Arara}% \listadd{\mylist}{Duck}% \renewcommand*{\do}[1]{#1. }% \dolistloop{\mylist}
produces:
Alternatively, you can provide your own handler instead of using \do
:
where ⟨handler cs⟩ is the command to use on each iteration of the list and ⟨list cs⟩ is the list control sequence. If you prefer to supply the list control sequence name without the leading backslash you can use:
Create a document that loads the sample booklist.csv file or the books SQL table. Then create an internal list that contains a list of all the book titles, without repetition. For example, if a title has both a hardback and paperback edition only add that title once rather than twice.
To test the list, iterate through it and display each item of the list.
(If you like, you can just use a paragraph break between items rather
than using a tabular
environment.) The result should look like:
This book is also available as A4 PDF or 12.8cm x 9.6cm PDF or paperback (ISBN 978-1-909440-07-4).