## 2.7.2⁂Iterating Over a Comma-Separated List

The etoolbox package [51] provides:

\docsvlist{item1,item2,…}

This iterates over the given comma-separated list and does

\do{item}

at each iteration, where ⟨item⟩ is the current item in the list. It's up to the user to define `\do` before using `\docsvlist`. For example:

```\renewcommand{\do}[1]{#1. }%
\docsvlist{Parrot,Canary,Zebra,Arara,Duck}
```

produces:

Alternatively you can provide your own handler instead of `\do` using

\forcsvlist{handler cs}{list}

For example:

```\newcommand{\mylistitem}[1]{#1. }%
\forcsvlist{\mylistitem}{Parrot,Canary,Zebra,Arara,Duck}
```

which again produces:

The argument `\docsvlist` (and `\forcsvlist`) doesn't get expanded, so if you try:

```\newcommand*{\mylist}{Parrot,Canary,Zebra,Arara,Duck}%
\renewcommand{\do}[1]{#1. }%
✘\docsvlist{\mylist}
```

then you'll only have a list with a single item (`\mylist`) so you'll just have the one iteration

```\do{\mylist} ```

which just produces:

Instead you need to make sure the argument is expanded before it's processed by `\docsvlist`:

```\newcommand*{\mylist}{Parrot,Canary,Zebra,Arara,Duck}%
\renewcommand{\do}[1]{#1. }%
✔\expandafter\docsvlist\expandafter{\mylist}
```

The `\expandafter` commands may look a bit confusing but the syntax is

\expandaftertoken 1⟩⟨token 2

This makes TeX expand ⟨token 2⟩ before it processes ⟨token 1⟩, so it's equivalent to:

token 1⟩⟨expansion of token 2
Therefore

 \expandafter \docsvlist \expandafter ↑ ↑ ⟨token 1⟩ ⟨token 2⟩

means that TeX must expand the thing after `\docsvlist` before it does `\docsvlist` (step ① in Figure 2.9), but that thing happens to be another `\expandafter`:

 \expandafter { \mylist ↗ ↑ ⟨token 1⟩ ⟨token 2⟩

This means that before TeX processes the left brace character { it must first expand the token after it (step ②), so that `\mylist` is replaced with its definition (step ③).

So TeX starts out with the first `\expandafter`, skips over `\docsvlist` ① and does the second `\expandafter` which makes TeX skip over the open brace ② and expand `\mylist`, which replaces `\mylist` with its definition ③.

Figure 2.9: Processing `\expandafter`

Once `\mylist` has been expanded, TeX then goes back to the `\docsvlist` command, which is now in the form:

`\docsvlist``{Parrot,Canary,Zebra,Arara,Duck}`

In the case of `\forcsvlist`, this becomes more complicated as the list is the second argument. However, since the first argument is just a single control sequence it doesn't need to be grouped and can therefore be skipped over with another `\expandafter`. For example:

```\newcommand*{\mylist}{Parrot,Canary,Zebra,Arara,Duck}%
\newcommand{\mylistitem}[1]{#1. }%
\expandafter\forcsvlist\expandafter\mylistitem\expandafter{\mylist}
```

The datatool package also provides some comma-separated list related commands:

\DTLifinlist{item}{list}{true}{false}

This checks if the given item is in ⟨list⟩. A one-level expansion is performed on ⟨list⟩ but not on ⟨item⟩.

\DTLnumitemsinlist{list}{cs}

This counts the number of non-empty items in ⟨list⟩ and stores the result in the control sequence ⟨cs⟩. Again, a one-level expansion is performed on ⟨list⟩.

Example:

```\newcommand{\mylist}{Parrot,Canary,Zebra,Arara,Duck}%
Parrot
\DTLifinlist{Parrot}{\mylist}{is}{isn't}
in the list.
Number of items in the list:
\DTLnumitemsinlist{\mylist}{\numitems}\numitems.
```

produces:

Spaces

Remember what I mentioned earlier about being careful of spaces? Here's an illustration of unexpected behaviour involving spaces in lists:

```\renewcommand{\do}[1]{``#1''. }%
\docsvlist{ Parrot , Canary , Zebra , Arara , Duck }
```

This produces:

The leading spaces have been ignored but the trailing spaces are still present.

The LaTeX kernel has a command that can also iterate through a comma-separated list but it's an internal command:

\@forcs⟩:=⟨list⟩\do{body}

This iterates through ⟨list⟩ and assigns the control sequence ⟨cs⟩ to the current item in the list so that it can be used as a placeholder in ⟨body⟩. Note that in this context `\do` doesn't refer to etoolbox's `\do` handler macro but is used as an argument delimiter (so it's like plain TeX syntax rather than LaTeX syntax). Since `\@for` is an internal command it should only be used in a package or class file. If it has to be used in the document, it should be placed between `\makeatletter` and `\makeatother` like this:

```\makeatletter
\@for\thisitem:=Parrot,Canary,Zebra,Arara,Duck\do{\thisitem. }
\makeatother
```

This produces:

The `\@for` command expands the list so:

```\newcommand*{\mylist}{Parrot,Canary,Zebra,Arara,Duck}%
\makeatletter
\@for\thisitem:=\mylist\do{\thisitem. }
\makeatother
```

produces the same result as above. However, now let's look at what happens when we introduce spaces into the list again:

```\makeatletter
\@for\thisitem:= Parrot , Canary , Zebra , Arara , Duck \do
{``\thisitem''. }
\makeatother
```

This produces:

In this case both the leading and trailing spaces have been retained.

The etextools package [15] also provides commands to iterate over lists. For example:

\csvloop[auxiliary commands]{list}

The `\csvloop` macro iterates over the comma-separated list given in ⟨list⟩ (which may be a macro that expands to a list) and at each iteration does ⟨auxiliary commands⟩. If this optional argument is missing, `\do` is assumed, which behaves in the same way as with etoolbox's `\docsvlist` command. So

```\renewcommand{\do}[1]{#1. }%
\csvloop{Parrot,Canary,Zebra,Arara,Duck}
```

produces

Now let's try with spaces again:

```\renewcommand{\do}[1]{``#1''. }%
\csvloop{ Parrot , Canary , Zebra , Arara , Duck }
```

This produces:

In this case the leading space has been retained on the first item, but not on any of the other items, but all the trailing spaces have been retained.

This section introduces one of etextools commands for illustrative purposes, but some of the commands in etextools and etoolbox conflict. For example, both packages define a command called `\forlistloop` but the syntax is incompatible. Since datatool automatically loads etoolbox this means that datatool and etextools may also conflict.

Another package is pgffor (part of the pgf bundle [102]) which provides:

\foreachvariables[options] in {list}{body}

where ⟨list⟩ is either an explicit comma-separated list or a control sequence that expands to a comma-separated list. The syntax can get quite complicated, but the simplest version is in the form:

```\foreach \thisitem in {Parrot,Canary,Zebra,Arara,Duck}
{\thisitem. }
```

which produces:

Now let's try with spaces:

```\foreach \thisitem in { Parrot , Canary , Zebra , Arara , Duck }
{``\thisitem''. }
```

This produces:

which is the same result as with `\docsvlist` where the trailing spaces have been retained but not the leading spaces.

This is why it's important to ensure any spurious spaces are removed from comma-separated lists in your source code. It may be that some commands trim all spaces (for example in the optional argument of `\usepackage` or `\documentclass`),6 while some commands only trim leading spaces (as with `\docsvlist` and `\foreach`) but others don't trim any spaces (such as `\cite`, which internally uses `\@for`). Remember that you can comment out space caused by the EOL character, and spaces at the start of lines are automatically discarded by TeX, so to make your code clearer you can do, for example:

```\docsvlist
{%
Parrot,%
Canary,%
Zebra,%
Arara,%
Duck%
}
```

If you comment an EOL character that would naturally be discarded (for example, following a control sequence) there's no harm done, but if you forget to comment an unwanted EOL character, you can end up with weird spaces in your document or an error message.

Empty Items

In addition to watching out for spurious spaces, you also need to consider what happens if you have an empty item in your list. Do you want empty items skipped or should they be processed either in the same way as the other items or by displaying a missing data symbol, such as an em-dash? Let's look at how the above comma-separated list processing commands deal with this type of situation:

```\renewcommand{\do}[1]{``#1''. }

\docsvlist{,Parrot,Canary,Zebra,,Arara,Duck}

\csvloop{,Parrot,Canary,Zebra,,Arara,Duck}

\foreach\thisitem in {,Parrot,Canary,Zebra,,Arara,Duck}
{``\thisitem''. }

\makeatletter
\@for\thisitem:=,Parrot,Canary,Zebra,,Arara,Duck\do
{``\thisitem''. }
\makeatother```

The result is:

So `\docsvlist` and `\csvloop` both skip empty items but `\foreach` and `\@for` don't.

Exercise 3. Iterating Through a List

Create a document that defines the commands:

```\newcommand*{\mylistI}{A,B,C,D}
\newcommand*{\mylistII}{a,b,c,d}
```

then create the `tabular` environment shown in Table 2.8 using `\docsvlist` to construct columns 2 to 5 for each row.

 List 1: List 2: A B C D a b c d

Next, redefine `\mylistII` so the third item is empty and redo the `tabular` environment. Finally, define a command called `\missingdata` that does nothing and redefine `\mylistII` so the third item is `\missingdata` and redo the `tabular` environment.

In fact, all spaces are stripped from the optional argument of those two commands, so it's technically possible to do, say, `\usepackage``[dr aft]{graphics}` although I don't recommend you do this.