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.
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It only takes a minute to sign up.
Sign up to join this communityIt'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.
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. :)
\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.
Mar 29, 2013 at 18:29
\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.
A loop and a counter:
\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}
The length of the list 0,1,54,1,3 is 5.
xstring
, counting empty elementsA 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}
kvsetkeys
, counting non-empty elementsThe 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}
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.
\renewcommand*{\do}[1]{\stepcounter{itemcounter}}
when gobble it anyway?
Apr 27, 2013 at 18:38