# Trouble parsing array with single item

I am trying to parse arrays of strings, but when I create an array of containing a single string (say the string contains n characters), it is not parsed correctly, instead it's parsed as containing n items, with each item an individual character. can anyone shed some light on why does this happen? thanks in advance! Code and output below:

\documentclass{article}
\usepackage{pgfmath,pgffor}
\begin{document}

\noindent Array 1 is \{"this","is","cool"\}

\def\myArray{{"this","is","cool"}}

\pgfmathparse{dim(\myArray)}
\edef\myArrayLength{\pgfmathresult}

\pgfmathparse{\myArrayLength-1}
\edef\lastIndex{\pgfmathresult}

\foreach \i in {0,...,\lastIndex}
{
\noindent Array 1, item \i: \pgfmathparse{\myArray[\i]}\pgfmathresult \newline
}

\noindent Array 2 is \{"not cool"\}

\def\singleItemArray{{"not cool"}}

\pgfmathparse{dim(\singleItemArray)}
\edef\singleItemArrayLength{\pgfmathresult}

\pgfmathparse{\singleItemArrayLength-1}
\edef\lastIndex{\pgfmathresult}

\foreach \i in {0,...,\lastIndex}
{
\noindent Array 2, item \i: \pgfmathparse{\singleItemArray[\i]}\pgfmathresult \newline
}
\end{document}


• Interestingly, there is no formal definition for arrays, just a few examples. It's not the space, because {{"notcool"}} produces the same issue. Length one arrays seem to be invalid, as {{12}} turns out to have length two as well. Oct 21 '17 at 22:38
• To work around this bug/feature, you can enclose each element into braces: \def\myArray{{{"this"},{"is"},{"cool"}}}, \def\myArray{{{"not cool"}}}... Oct 22 '17 at 7:29

I found a solution with an other array length command and some if...else statements to handle the single item arrays, which are causing problems.

Step 1: Compute the size of an array with code by @Alain Matthes

\def\getlen#1{%
\pgfmathsetmacro{\lenarray}{0}%
\foreach \i in #1{%
\pgfmathtruncatemacro{\lenarray}{\lenarray+1}%
\global\let\lenarray\lenarray}%
}


Example: define array \def\mar{1,2},compute length \getlen{\mar} and get value \lenarray %=> '2'

Note: length of the array is stored in \r with \edef\r{\lenarray}.

Step 2: Expand the single array:

\ifnum\r=1
\def\myArray{{\myArrayRoh,"\relax "}}
\else
\def\myArray{{\myArrayRoh}}
\fi


Step 3: ... so you have to reduce the last item index with 2 instead of 1 for every single array:

\ifnum\r=1
\pgfmathparse{\myArrayLength-2} % single item
\else
\pgfmathparse{\myArrayLength-1} % multiple items
\fi


Result:

MWE:

\documentclass[varwidth,border=7]{standalone}
\usepackage{tikz}

% https://tex.stackexchange.com/a/66159/124842 (@Alain Matthes)
\def\getlen#1{%
\pgfmathsetmacro{\lenarray}{0}%
\foreach \i in #1{%
\pgfmathtruncatemacro{\lenarray}{\lenarray+1}%
\global\let\lenarray\lenarray}%
}
\begin{document}
\def\myArrayRoh{"this"} % singleItemArray

\getlen{\myArrayRoh}
\edef\r{\lenarray}

\ifnum\r=1
\def\myArray{{\myArrayRoh,"\relax "}}
\else
\def\myArray{{\myArrayRoh}}
\fi
%
\pgfmathparse{dim(\myArray)}
\edef\myArrayLength{\pgfmathresult}

\ifnum\r=1
\pgfmathparse{\myArrayLength-2}
\else
\pgfmathparse{\myArrayLength-1}
\fi

\edef\lastIndex{\pgfmathresult}

\foreach \i in {0,...,\lastIndex}
{
\noindent Array 1, item \i: \pgfmathparse{\myArray[\i]}\pgfmathresult \newline
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\def\myArrayRoh{"this","is","cool"} % multiItemArray

\getlen{\myArrayRoh}
\edef\r{\lenarray}

\ifnum\r=1
\def\myArray{{\myArrayRoh,"\relax "}}
\else
\def\myArray{{\myArrayRoh}}
\fi

\pgfmathparse{dim(\myArray)}
\edef\myArrayLength{\pgfmathresult}

\ifnum\r=1
\pgfmathparse{\myArrayLength-2}
\else
\pgfmathparse{\myArrayLength-1}
\fi

\edef\lastIndex{\pgfmathresult}

\foreach \i in {0,...,\lastIndex}
{
\noindent Array 2, item \i: \pgfmathparse{\myArray[\i]}\pgfmathresult \newline
}
\end{document}

• Hey @Bobyandbob - very nice, thanks :) Oct 23 '17 at 23:09

I would suggest to use xstring for a simple string item or listofitems for separated items:

\documentclass{article}
\usepackage{xstring}
\usepackage{pgffor}
\usepackage{listofitems}

\begin{document}

{\bfseries xstring on list:}\vspace{10pt}

\def\myarray{not cool}
\StrLen{\myarray}[\MyStrLen]

Items of "\myarray": \MyStrLen\par
\foreach \i in {1,...,\MyStrLen}{Item \i: \StrMid{\myarray}{\i}{\i}''\par}\vspace*{20pt}

{\bfseries listofitems on list:}\vspace{10pt}

\setsepchar{,}
\def\mylist{test item, {another item}, third item}

Items of "\mylist":\commalistlen\par
\foreachitem\x\in\commalist{Item \xcnt: \x''\par}

\end{document}


Output:

Edit after comment:

For one item list, listofitems is still an option.

\setsepchar{,}
\def\mylist{"not cool"}

Items of "\mylist":\commalistlen\par
\foreachitem\x\in\commalist{Item \xcnt: \x''\par}\vspace{20pt}


We get the desired result:

PS: There is a problem if we enclose the item inside {} that I thing have to be reported to maintainer.

• Aren't you missing the point here? The idea is to not parse the second one char by char. I think adding answers about a related issue just in case someone find this in a search while looking for something else is a bad idea. Oct 21 '17 at 20:07
• @TorbjørnT. You are right. But I wasn't really off topic. I just gave a solution on such problems (more for newbies). I edited and added an one item list parsed with listofitems... I still thing this is not the answer that the OP is looking for, but solves such problems (of pursing an one item list-array). I just found an error of the package that I will report to the maintainer so, that the list can be read exactly as the OP is giving it. Oct 21 '17 at 21:40
• The maintainer of listofitems (@Christian Tellechea) just informed me that he will try to fix the bug as soon as possible. Oct 22 '17 at 8:08

I'm not sure this is a bug of PGF, as there's no formal definition of what an array is; but it turns out that an array must not have length one:

\documentclass{article}
\usepackage{pgfmath,pgffor}
\begin{document}

\verb|\def\myArray{{"this","is","cool"}}|
\def\myArray{{"this","is","cool"}}

\pgfmathsetmacro\myArrayLength{dim(\myArray)}

\pgfmathsetmacro\lastIndex{\myArrayLength-1}

\foreach \i in {0,...,\lastIndex}
{
Array 1, item \i: \pgfmathparse{\myArray[\i]}\pgfmathresult\par
}

\verb|\def\myArray{{"notcool"}}|
\def\myArray{{"notcool"}}

\pgfmathsetmacro\myArrayLength{dim(\myArray)}

\pgfmathsetmacro\lastIndex{\myArrayLength-1}

\foreach \i in {0,...,\lastIndex}
{
Array 2, item \i: \pgfmathparse{\myArray[\i]}\pgfmathresult\par
}

\verb|\def\myArray{{12}}|
\def\myArray{{12}}

\pgfmathsetmacro\myArrayLength{dim(\myArray)}

\pgfmathsetmacro\lastIndex{\myArrayLength-1}

\foreach \i in {0,...,\lastIndex}
{
Array 3, item \i: \pgfmathparse{\myArray[\i]}\pgfmathresult\par
}
\end{document}


The last example gives the same result as with \def\myArray{{1,2}}.