# How to use data structures in TikZ?

I created a foreach statement, using expl3 and TikZ/pgf:

\documentclass{article}
\usepackage{tikz}
\setlength{\parindent}{0cm}
\usepackage{expl3}
\ExplSyntaxOn
\cs_new:Npn \Counter #1 \Stopper { \tl_length:n {#1} }
\ExplSyntaxOff
\pgfmathdeclarefunction{countarray}{1}{\edef\pgfmathresult{\Counter#1\Stopper}}
\begin{document}
%array with names
\def\names{{"Katie","Frank","Laura"}}

%find the last element index
\pgfmathtruncatemacro{\Last}{countarray(\names) - 1}

%print all the elements of array
\foreach \i in {0,...,\Last} {%
\i: \pgfmathparse{\names[\i]}\pgfmathresult\\
}
\end{document}

Prints this:

Suppose I want to use different colors for different names (or setting any other parameters). Getting something like this:

Katie\\
\textcolor{blue}{Frank}\\
Laura

In Perl, I would have done something like this:

my @data = (
{"text" => "Katie"},
{"text" => "Frank", "color" => "blue"},
{"text" => "Laura"});

foreach(@data)
{
if(defined($_->{color})) { print "\textcolor\{$_->{color}\}\{$_->{text}\}"; } else { print$_->{text};
}
print "\\\\";
}

Is it possible to implement this in expl3?

-
Is there a reason for storing the names in the format you have rather than a normal comma list? Can we use just expl3 data constructs to make everything work? Are we allowed a separate 'color' data structure to hold the info or does it all need to be in one place? – Joseph Wright Apr 10 '13 at 12:48
@JosephWright The benefit of storing data in this format is that it allows to have some values missing in the record. While in a comma separated list (array), you'll have to have empty cells. – user4035 Apr 10 '13 at 16:00
Does it need to be expl3? I would have suggested something between Ryan Reich’s and Claudio Fiandrino’s answer. — How do you want the input to look like without an empty-cells containing comma-separated list? – Qrrbrbirlbel Apr 11 '13 at 9:39
@Qrrbrbirlbel "Does it need to be expl3?" No, tikz is ok. I need to test the answers myself to fully understand, how to use them. Just need some time. – user4035 Apr 11 '13 at 10:04

I don't know about expl3 but it is possible within TikZ, or rather, within pgfkeys. Since there is an l3keys submodule of LaTeX3, I assume basically the same idea works there. You can create your data structure in much the same way as in Perl:

\pgfkeys{
/names/.cd,
make name/.style = {
#1/color/.initial = black
},
make name/.list = {Katie, Frank, Laura},
Frank/color = blue
}

Then you can extract the color of a name via, say:

\newcommand\getcolor[1]{%
\pgfkeysgetvalue{/names/#1/color}%
}

which is fully expandable and can be used wherever you need the color of a name. Of course, for this example there is no need for the single subkey Frank/color (you could just set Frank/.initial = blue) but if you want more properties, you can add them by giving them their own named subkeys as well.

-
The pgfkeys approach is object-oriented, which the keyval support in LaTeX3 is not. So you'd need a different approach: I'll try to suggest one later. – Joseph Wright Apr 11 '13 at 9:18

This ultimately does not answer to the question:

Is it possible to implement this in expl3?

thus it is marked community wiki.

Besides the interesting aspect of dealing with expl3, this job is perfectly doable just with the standard syntax of TikZ foreach in combination with xstring:

\documentclass{article}
\usepackage{tikz} % won't work just with pgffor
\setlength{\parindent}{0cm}
\usepackage{xstring}
\begin{document}

\foreach \name [count=\i from 0]in{Katie,Frank=>blue,Laura=>red}{
\IfSubStr{\name}{=>}{% true
\StrCut{\name}{=>}\xname\namecol
\i: \textcolor{\namecol}{\xname}\par%
}{% false
\i: \name\par%
}
}

\end{document}

This provides:

The idea behind is more or less like this:

1. look for the separator string (=> in the example);
2. if present cut the string into two parts (name and color) and use them;
3. if not present, use the standard syntax.

Of course, it is possible to:

• change separator string;
• do much more complicated things (i.e. adding more properties: just nest some conditionals or, in a simpler manner, define one separator string per property).
-
I think you're being overly modest in making this CW. It's not uncommon to give alternate solutions and the original question was not heavily LaTeX3-oriented; I suspect the poster was trying to learn about LaTeX programming rather than was tied to this particular model of it. And there are so many models. – Ryan Reich Apr 11 '13 at 14:21
I agree with you, but I've marked it as CW following the policy proposed by Charles in his meta answer to Best practise for answers which are for the community, not the OP (“tikz answer to pstricks question”) since this might be the case. – Claudio Fiandrino Apr 11 '13 at 19:06

Suppose, we want our code to support 2 properties of text: color and italics. At first we define the plists:

%plist1 definition
\prop_new:N \l_list_a_prop
\prop_put:Nnn \l_list_a_prop { text } {Katie}

%plist2 definition
\prop_new:N \l_list_b_prop
\prop_put:Nnn \l_list_b_prop { text } {Frank}
\prop_put:Nnn \l_list_b_prop { color } {red}

%plist3 definition
\prop_new:N \l_list_c_prop
\prop_put:Nnn \l_list_c_prop { text } {Laura}
\prop_put:Nnn \l_list_c_prop { color } {blue}
\prop_put:Nnn \l_list_c_prop { italic } {yes}

Mind, that expl3 doesn't support numbers in the names, that's why I used _a, _b, _c.

Then put all the plists into a sequence:

%putting plists to sequence
\seq_new:N \l_my_seq
\seq_push:Nn \l_my_seq { \l_list_c_prop }
\seq_push:Nn \l_my_seq { \l_list_b_prop }
\seq_push:Nn \l_my_seq { \l_list_a_prop }

Then we loop through the sequence and put the appropriate markup to the text if necessary:

\tl_new:N \__text
\seq_map_inline:Nn \l_my_seq
{
\prop_get:NnN #1 { text } \__text

\prop_get:NnNT #1 { color } \color_tl
{
\protected@edef \__text {\textcolor{\color_tl}{\__text}}
}

\prop_get:NnNT #1 { italic } \italic_tl
{
\protected@edef \__text {\textit{\__text}}
}

\__text\\
}

Altogether we have the following code:

\documentclass{article}
\usepackage{expl3}
\usepackage{color}
\setlength\parindent{0pt}
\begin{document}
\makeatletter
\ExplSyntaxOn

%plist1 definition
\prop_new:N \l_list_a_prop
\prop_put:Nnn \l_list_a_prop { text } {Katie}

%plist2 definition
\prop_new:N \l_list_b_prop
\prop_put:Nnn \l_list_b_prop { text } {Frank}
\prop_put:Nnn \l_list_b_prop { color } {red}

%plist3 definition
\prop_new:N \l_list_c_prop
\prop_put:Nnn \l_list_c_prop { text } {Laura}
\prop_put:Nnn \l_list_c_prop { color } {blue}
\prop_put:Nnn \l_list_c_prop { italic } {yes}

%putting plists to sequence
\seq_new:N \l_my_seq
\seq_push:Nn \l_my_seq { \l_list_c_prop }
\seq_push:Nn \l_my_seq { \l_list_b_prop }
\seq_push:Nn \l_my_seq { \l_list_a_prop }

\tl_new:N \__text
\seq_map_inline:Nn \l_my_seq
{
\prop_get:NnN #1 { text } \__text

\prop_get:NnNT #1 { color } \color_tl
{
\protected@edef \__text {\textcolor{\color_tl}{\__text}}
}

\prop_get:NnNT #1 { italic } \italic_tl
{
\protected@edef \__text {\textit{\__text}}
}

\__text\\
}
\ExplSyntaxOff
\makeatother
\end{document}

This will print:

-