Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

It's simple. I have a list like {0,1,54,1,3} as input argument to a command in making. How can I obtain the length of this list? Something like

\length(#1)

where #1 is the list.

share|improve this question
    
Welcome to TeX.sx! –  Peter Jansson Mar 29 '13 at 16:08
    
Since you have some responses below that seem to answer your question, please consider marking one of them as ‘Accepted’ by clicking on the tickmark below their vote count (see How do you accept an answer?). This shows which answer helped you most, and it assigns reputation points to the author of the answer (and to you!). It's part of this site's idea to identify good questions and answers through upvotes and acceptance of answers. –  Qrrbrbirlbel Sep 3 '13 at 17:24
add comment

4 Answers 4

My first LaTeX3 answer! Yay! :)

The l3clist package has a lot of built-in commands to deal with comma-separated lists. Here's an attempt:

\documentclass{article}

\usepackage{expl3}
\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand \countItems { m } {
    \clist_count:N #1
}

\NewDocumentCommand \countInlineItems { m } {
    \clist_count:n {#1}
}

\ExplSyntaxOff

\begin{document}

\def\mylist{0,1,54,1,3}

This list has \countInlineItems{0,1,54,1,3} elements.

And the same list has \countItems{\mylist} elements.

\end{document}

Please note that we have two different usages: one for a stored list (e.g, \mylist) and one for an inline list. Thanks to Joseph for point the flaws in my code. :)

Hope it helps. :)

share|improve this answer
    
Since this is LaTeX3, I won't dare assume that this is ok (although I tested it and it seems to work): A trick I have been using with non-LaTeX3 to have a single macro for these two cases is to ONLY use the one that works on macro defined lists, and do an \edef\TempList{#1} and then use TempList instead of #1. Then the macro is only ever working on a macro defined list, and you don't need to think about which version to call when using it... Perhaps there are inherent problems, but seems to be ok so far. All the solutions I posted using a \foreach in a macro should already do this. –  Peter Grill Mar 29 '13 at 18:29
1  
@PeterGrill You should never use \edef on unknown input in LaTeX2e: use \protected@edef. Even that may be risky, which is why we take care to define the difference between a variable and 'some tokens'. Also, if you want an expandable solution then \edef is out in any form. –  Joseph Wright Mar 29 '13 at 18:32
    
Shouldn’t the second \countInlineItems be \countItems? –  Qrrbrbirlbel Mar 29 '13 at 19:07
1  
@Qrrbrbirlbel: silly me, I forgot about that! :) Thank you. –  Paulo Cereda Mar 29 '13 at 19:14
add comment

A loop and a counter:

Code

\documentclass{article}
\makeatletter
\newcommand*{\length}[1]{%
    \@tempcnta\z@
    \@for\@tempa:=#1\do{\advance\@tempcnta\@ne}%
    The length of the list #1 is \the\@tempcnta.%
}
\makeatother
\begin{document}
\length{0,1,54,1,3}

\def\mylist{0,1,54,1,3}
\length\mylist
\end{document}

Output

The length of the list 0,1,54,1,3 is 5.

share|improve this answer
add comment

Package xstring, counting empty elements

A solution using package xstring. It also counts elements that are empty:

\documentclass{article}
\usepackage{xstring}
\newcommand*{\commalength}[1]{%
  \StrCount{#1,}{,}%
}
\begin{document}
\verb|{0,1,54,1,3}| has length \commalength{0,1,54,1,3}.

\verb|{,,}| has length \commalength{,,}.
\end{document}

Result

Package kvsetkeys, counting non-empty elements

The parser \comma@parse of package kvsetkeys removes an optional space before and after an entry and removes empty entries.

\documentclass{article}

\usepackage{kvsetkeys}
\makeatletter
\newcommand*{\commalength}[1]{%
  \begingroup
    \count@=0 %
    \comma@parse{#1}{%
      \advance\count@ by 1 %
      \@gobble
    }%
    \the\count@
  \endgroup
}
\makeatother

\begin{document}
\verb|{0,1,54,1,3}| has length \commalength{0,1,54,1,3}.

\verb|{,,}| has length \commalength{,,}.
\end{document}

Result

share|improve this answer
add comment

Let's try etoolbox.

This use the loop and counter approach.

\documentclass{article}

\usepackage{etoolbox}

\makeatletter
\newcounter{itemcounter}%
\newcommand{\length}[1]{%
    \setcounter{itemcounter}{0}%
    \renewcommand*{\do}[1]{\stepcounter{itemcounter}\@gobble{##1}}%
    \docsvlist{#1}%
    \theitemcounter%
}
\makeatother

\begin{document}
\length{1}\qquad \length{1,2}\qquad \length{1,2,3,f,t,w,x,y,z}
\end{document}

The command \@gobble discards its argument.

share|improve this answer
    
Why don't you just do \renewcommand*{\do}[1]{\stepcounter{itemcounter}} when gobble it anyway? –  Qrrbrbirlbel Apr 27 '13 at 18:38
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.