30

I'm trying to generate a lot of name badges. I'm wondering, is it possible to store the names as strings in one array, according to the PGF manual:

\def\myarray{{1,"two",2+1,"IV","cinq","sechs",sin(\i*5)*14}} 

I tried this:

\def\names{{"Katie","Frank","Laura","Joe"}}

Without success, because it seems to store the whole string in \names variable, and if I write

\names[2]

The output will be

"Katie","Frank","Laura","Joe" 

instead

Laura  

is what I want to write out.

So why is this not working? How could I use arrays? Does it require some special library?

3
  • Is this for using in a foreach loop?
    – percusse
    Feb 19, 2012 at 17:11
  • 4
    Here is an example that does not require quotes: \begin{tikzpicture} \def\mylist{Laura,Katie,Frank,Joe} \foreach[count=\xi] \x in \mylist \node[minimum width=1cm] (n\xi) at (\xi,\xi) {\x}; \end{tikzpicture}. The quotes are needed when you plugin your list into a macro and to protect the text from a math parser!
    – percusse
    Feb 19, 2012 at 17:19
  • No, i use it not in a foreach loop. Without foreach loop somehow it doesn't work for me, it gives back the whole string. Thanks!
    – deeenes
    Feb 19, 2012 at 21:04

4 Answers 4

27

This answer may be more generic than specifically relating to TikZ/PGF.

(La)TeX is a macro-based language, so it does not work as expected compared to other languages when dealing with "arrays". For example, while \names[2] should yield Laura where

\def\names{Katie, Frank, Laura, Joe}

(indexing from 0), (La)TeX considers [2] to have no connection to \names. As such, you're more likely to obtain the output Katie, Frank, Laura, Joe[2] - a concatenation of \names (as it is defined) and [2].

In order to allow for indexing like one typically would using arrays, you would need some other functionality. Here's an example of a list parser that works like you would expect arrays do:

enter image description here

\documentclass{article}
\usepackage{xparse}% http://ctan.org/pkg/xparse
\usepackage{etoolbox}% http://ctan.org/pkg/etoolbox
\newcounter{listtotal}\newcounter{listcntr}%
\NewDocumentCommand{\names}{o}{%
  \setcounter{listtotal}{0}\setcounter{listcntr}{-1}%
  \renewcommand*{\do}[1]{\stepcounter{listtotal}}%
  \expandafter\docsvlist\expandafter{\namesarray}%
  \IfNoValueTF{#1}
    {\namesarray}% \names
    {% \names[<index>]
     \renewcommand*{\do}[1]{\stepcounter{listcntr}\ifnum\value{listcntr}=#1\relax##1\fi}%
     \expandafter\docsvlist\expandafter{\namesarray}}%
}
\begin{document}
\newcommand{\namesarray}{Katie, Frank, Laura, Joe}%
\verb|\names:|\ \names \par
\verb|\names[2]:|\ \names[2] \par
\verb|\names[0]:|\ \names[0] \par
\verb|\names[5]:|\ \names[5]
\end{document}

The idea here is to store the names in an array \namesarray and then define a macro (or "function") that takes an optional argument. If no argument is supplied (i.e., you just use \names), then you print the entire \namesarray. If an argument is supplied (of the form \names[<index>]), parse the list sequentially to find that item that matches <index> and print it.

The list parser relies on etoolbox's \docsvlist and enumerator \do.

3
  • 1
    Wow, you implemented it very professionally! It works fine. I'm just adding one comment: i can get the values of the array with a counter, like this: \newcounter{i} \setcounter{i}{0} \names[\value{i}] \stepcounter{i} ...So it's perfect!
    – deeenes
    Feb 19, 2012 at 21:08
  • Is it possible to get the size of the array? (I would like to use it in a \forloop)
    – Zach
    Sep 8, 2016 at 18:28
  • 1
    @Zach: You can use \sbox9=\hbox{\names} (processes \names but doesn't print it) which then allows you to use the listtotal counter that holds the number of items in the list.
    – Werner
    Sep 8, 2016 at 18:46
43

To answer the specific question you are asking, here is a complete minimal example.

\documentclass{standalone}
\usepackage{pgfmath}
\begin{document}
\def\names{{"Katie","Frank","Laura","Joe"}}%
\pgfmathparse{\names[2]}\pgfmathresult
\end{document}

So, you need to use the pgfmath parser to do the job through \pgfmathparse and then use the result of the parsing with \pgfmathresult: in other words, you cannot call \names[2] directly.

Here is a more complete example with a \foreach loop:

\documentclass{standalone}
\usepackage{pgfmath,pgffor}
\begin{document}
\def\names{{"Katie","Frank","Laura","Joe"}}%
\foreach \i in {0,...,3} {%
  Name \i: \pgfmathparse{\names[\i]}\pgfmathresult, }
\end{document}
3
  • So now it's clear for me, what i need to make it work like in the PGF manual. Thanks!
    – deeenes
    Feb 19, 2012 at 21:19
  • 1
    Your second snippet doesn't work for me. Gives an error: Undefined control sequence. \pgfkeys. After replacing \usepackage{pgfmath,pgffor} to \usepackage{tikz} it worked.
    – user4035
    Apr 23, 2013 at 22:54
  • Where is this syntax documented? I searched the documentation and found nothing...
    – Dror
    Mar 31, 2014 at 13:22
14

The arrayjob package has some more macros for using the data array.

\documentclass{article}
\usepackage{arrayjob}

\newarray\names
\readarray{names}{Katie&Frank&Laura&Joe}

\begin{document}
\verb|\names(3):|\ \names(3) \par
\verb|\names(1):|\ \names(1) \par
\verb|\names(5):|\ \names(5)
\end{document}

enter image description here

Note:
The arrays are 1 based (index starts at 1)

0
8

You don't need arrays (but arrays are described in the pgf manual). Also you don't need numbers to "index" the arrays.

\documentclass{beamer}
\usepackage{tikz}
   \pgfkeys{/English to German/Peter/.code=Peter,
            /English to German/Mary/.code=Maria,
            /German to English/Peter/.code=Peter,
            /German to English/Maria/.code=Mary}

\pgfkeys{/English to German/Peter}, % -> Peter
\pgfkeys{/English to German/Mary}, % -> Maria
\pgfkeys{/German to English/Peter}, and % -> Peter, and
\pgfkeys{/German to English/Maria}. % -> Mary.
\end{document}
3
  • It's easy, and works good. If i understand good, with this solution, i can define only one list?
    – deeenes
    Feb 19, 2012 at 21:13
  • No, you can have several lists. I've changed my example to show this.
    – user10274
    Feb 20, 2012 at 1:07
  • @user10247: please insert \begin{document} into your code.
    – Black Mild
    Sep 5, 2018 at 8:41

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .