# How to refer to number of items in a list before the list appears in the .tex file?

I would like LaTeX to "know" how many items there are in a certain list. I want this number to be stored in a variable. In such a way I hope that this variable is sampled during the first compilation and available for the next compilations. Then I can refer to the number of items in my text before the list appears in the same text. How can I accomplish that? My minimum example does not work. Thanks in advance :)

\documentclass[10pt,a4paper,twosided]{article}
\usepackage{etoolbox}

\begin{document}

%The following list contains \NumberOfItems\ items

\begin{enumerate}

\item item A
\item item B
\item item C

\end{enumerate}
\newcommand{\NumberOfItems}{\value{enumi}}

The previous list contains \NumberOfItems\ items

\end{document}

• I believe that your question addresses the same problem as this one: tex.stackexchange.com/questions/74595/… Please tell us if it is the case. If so, we could mark this as a duplicate. – yo' Feb 7 '13 at 11:40
• @tohecz That question is specifically tailored for itemize. – egreg Feb 7 '13 at 11:42
• Are my changes what you asked for? – myotis Feb 8 '13 at 11:25
• No, these aren't. However, you can exactly use \getrefnumber{firstlist} in place of your \NumberOfItems (requires the package refcount; firstlist is just the label assigned to the environment with enumeratecount) as I showed in my previous answer. – egreg Feb 8 '13 at 11:27

If you plan to use this only for first level lists and don't plan to use the enumitem package for personalizing the environment, using a \label in the last item is sufficient.

However a general solution that allows for rearrangement of items without bothering with the position of \label, is compatible also with enumitem and also works for nested list can be the following:

\documentclass[a4paper]{article}

\makeatletter
\newenvironment{enumeratecount}[1]
{\def\thisenumeratecountlabel{#1}\enumerate}
{\edef\@currentlabel{\number\value{\@enumctr}}%
\label{\thisenumeratecountlabel}\endenumerate}
\makeatother

\begin{document}

The following list contains~\ref{firstlist} items, while
the nested list contains~\ref{innerlist}.

\begin{enumeratecount}{firstlist}
\item item A
\item item B
\begin{enumeratecount}{innerlist}
\item sub A
\item sub B
\end{enumeratecount}
\item item C
\end{enumeratecount}

The previous list contains \ref{firstlist} items, while the
inner list contains~\ref{innerlist}.

\end{document}


You just use \begin{enumeratecount}{<label>} for stating the label to be used (before or after the environment) for getting the number of items.

If you use enumitem you can even say

\begin{enumeratecount}{<label>}[<enumitem settings>]


so, for instance,

\begin{enumeratecount}{mylist}[label=\Alph*]


would work correctly (which wouldn't with the "simple method" outlined above and in Ulrike's answer).

The solution uses a couple of facts: a \label command refers to the current value of \@currentlabel, so before doing \endenumerate we define \@currentlabel to be the complete expansion of \value{\@enumctr}. The macro \@enumctr expands to enumi, enumii, enumiii or enumiv depending on the nesting level of the current enumerate environment; thus we're guaranteed to get the right number at all levels. Then we say \label{\thisenumeratecountlabel} that will set the label name to the original argument to enumeratecount. Locality of environments does the rest.

## An extension

Suppose we want to say "the following list contains 1 item" or "the following list contains 3 items", adding the "s" conditionally.

This can be done with the help of the refcount package.

\usepackage{refcount}
\newcommand{\addphrase}[3]{% #1 = label, #2 = text if number >1, #3 = text if number =1
\ifnum\getrefnumber{#1}>1
#2%
\else
#3%
\fi}


So the text above can be generated by

the following list contains \ref{firstlist}~\addphrase{firstlist}{items}{item}

• Thanks a lot ! How can I use \ref{firstlist} in a if-then-else decision? Something like \ifnumcomp{\ref{firstlist}{>}{1}{do this}{else, do that} – myotis Feb 7 '13 at 16:56
• @EspenDonali I've added some code. – egreg Feb 7 '13 at 17:16
• Thank again, but it is not exactly what i need. I need a new variable, made by \newcommand, with the value \ref{firstlist}, then I can use this variable in whatever commads from etoolbox. – myotis Feb 7 '13 at 17:20
• @EspenDonali Please, make a new question, so that you can explain more clearly what you want, with some examples. – egreg Feb 7 '13 at 17:44
• Sure : ), and thanks to both of you giving me answers thus far! – myotis Feb 8 '13 at 9:46

In your example already \ref gives the correct output:

\documentclass[10pt,a4paper,twosided]{article}
\usepackage{etoolbox}

\begin{document}

The following list contains \ref{a} items

\begin{enumerate}

\item item A
\item item B
\item\label{a} item C

\end{enumerate}
\end{document}

• Not if the list is nested. – egreg Feb 7 '13 at 11:48
• @egreg: I know. It also doesn't work if e.g. the numbering sheme is changed. That's why I wrote carefully "in the example ..." ;-). But I don't think that the question makes sense with nested lists. Would you write "The sub list of the second item hat 3 items?". – Ulrike Fischer Feb 7 '13 at 11:56

Q: How can I count the number of items and store this number in a command by Q:\newcommand?

A: Add a counter to item

\let\olditem\item
\AtBeginEnvironment{enumerate}{
\renewcommand{\item}{%
\olditem%
\stepcounter{mytempnumber}%
}}


As always one cannot redefine a macro recursive (that's why we need \let). I would like to recommend to use a counter for a number, not a macro.

Q: How can this be done, so that the value of this variable carries over to the next compilation where it can be available for "My conditional text" ?

A: Write it out! You can do this as value only, or as assignment:

\AtEndDocument{%
\openoutputfile{\jobname.num}{number}
\noexpand\setcounter{mynumber}{\themytempnumber}}
\closeoutputstream{number}
}


We need to handle expansion carefully here, since everything is expanded when wrote to a file.

Here's the complete code:

\documentclass{article}
\usepackage{etoolbox}

\usepackage{newfile}

\newoutputstream{number}

\newcounter{mynumber}
\newcounter{mytempnumber}

\let\olditem\item
\AtBeginEnvironment{enumerate}{
\renewcommand{\item}{%
\olditem%
\stepcounter{mytempnumber}%
}}

\AtEndDocument{%
\openoutputfile{\jobname.num}{number}
\noexpand\setcounter{mynumber}{\themytempnumber}}
\closeoutputstream{number}
}

\AtBeginDocument%
{%
\IfFileExists{\jobname.num}{\input{\jobname.num}}{\message{NO \jobname.num rerun!}}%
}

\begin{document}

\themynumber% use as normal counter

\begin{enumerate}
\item Issue A
\item Issue B
\item Issue C
\item
\end{enumerate}

\end{document}


I used etoolbox to hook into the enumerate environment and newfile to do the i/o stuff but more convenient. A interested user will notice, that the file <main file name>.num contents only one line of code: \setcounter{mynumber}{4}. So it's important to include the file before the usage of the counter.

• Thanks for your thorough anwer! I will study it to see if I understand it, and then possibly implement it :) – myotis Feb 8 '13 at 13:59

I used the ifthen package instead of etoolbox as I am more familiar with the former; there is likely a similar construct in the latter. Create a new counter, say itemnum. Set the value of the counter at then end of your enumerate command. Then a little trickery: take 1 from the counter, then refstepcounter it, which adds one back and allows you to save its value in a label. The \ifthenelse command uses its value and compares it to 1.

This, of course, takes 2 runs to take effect as does any \label & \ref combination.

\documentclass[10pt,a4paper,twosided]{article}
\usepackage{ifthen}

\newcounter{itemnum}

\begin{document}

This report will addresses the following
\ifthenelse{\ref{label:itemnum}=1}{issue}{issues}.

\begin{enumerate}

\item Issue A
\item Issue B
\item Issue C
\setcounter{itemnum}{\value{enumi}}