PGFMath has an array parser which can be used for this. The syntax is {comma delimited list}[index]
. You need the outer braces so to use it on \johnlist
you'd need to add the braces in. As coordinates are passed through pgfmath then you can use this as-is in coordinate specifications, in other uses you need to use \pgfmathparse
(or one of its variants).
\documentclass{article}
\usepackage{tikz}
\begin{document}
\def\johnlist{2,3,5,7}
\begin{tikzpicture}
\node[shape=circle,draw=black] at ({\johnlist}[0],0) {\pgfmathparse{{\johnlist}[0]}\pgfmathresult};
\end{tikzpicture}
\end{document}
Getting the tail involves counting how many entries there are in the list. Fortunately, PGFMath has a function for this as well. (This does not seem to be in the manual, I came across it when looking in the code to see how it knew where the end of the array was.) The function is dim(<array>)
. This gives the total number of entries so as PGF arrays are 0-indexed you need to subtract 1 to get the last element.
Full code:
\documentclass{article}
%\url{http://tex.stackexchange.com/q/115730/86}
\usepackage{tikz}
\begin{document}
\def\johnlist{2,3,5,7}
\begin{tikzpicture}
\node[shape=circle,draw=black] at ({\johnlist}[0],0)
{\pgfmathparse{{\johnlist}[0]}\pgfmathresult};
\node[shape=circle,draw=black] at
({{\johnlist}[dim({\johnlist})-1]},0)
{\pgfmathparse{{\johnlist}[dim({\johnlist})-1]}\pgfmathresult};
\end{tikzpicture}
\end{document}
Note the extra braces when in the coordinate to protect the inner ()
from confusing the parser.
(Added later) Looks like I misunderstood the meaning of the word "tail". This is stretching PGF's array handling quite a bit so I would seriously recommend jumping to LaTeX3 very soon. Nevertheless, it is possible to get a dynamic tail:
\pgfmathsetmacro\len{dim({\johnlist})-1}
\foreach[evaluate=\x as \x using {{\johnlist}[\x]}] \x in {1,...,\len}
\node[draw=red] at (\x,0) {\x};
This could be used more generally to get an array slice of some fashion.
(Added again)
The request in comments was for a proper slice so that one could save the slice of an array for reuse. This does not exist in PGFMath, but with a little hackery it can be implemented. It does not have a shortcut notation, and it doesn't behave well when mixed with the array element shortcut notation. Moreover, PGFMath internally converts lists into token lists so if we're staying within a PGFMath context we need to return a token list but if we want to save the list for reuse we need to return a comma-separated list. So there are two functions splice
and csvsplice
for these two contexts.
\documentclass{article}
%\url{http://tex.stackexchange.com/q/115730/86}
\usepackage{tikz}
\makeatletter
\pgfmathdeclarefunction{slice}{3}{%
\begingroup%
\def\pgfmath@csv{}%
\afterassignment\pgfmath@gobbletilpgfmath@\pgfmath@count=#2\relax\pgfmath@%
\afterassignment\pgfmath@gobbletilpgfmath@\c@pgfmath@counta=#3\relax\pgfmath@%
\advance\c@pgfmath@counta by -\pgfmath@count\relax
\expandafter\pgfmathslice@@#1\pgfmath@stop%
}
\pgfmathdeclarefunction{csvslice}{3}{%
\begingroup%
\def\pgfmath@csv{,}%
\afterassignment\pgfmath@gobbletilpgfmath@\pgfmath@count=#2\relax\pgfmath@%
\afterassignment\pgfmath@gobbletilpgfmath@\c@pgfmath@counta=#3\relax\pgfmath@%
\advance\c@pgfmath@counta by -\pgfmath@count\relax
\expandafter\pgfmathslice@@#1\pgfmath@stop%
}
\def\pgfmathslice@@#1{%
\def\pgfmath@temp{#1}%
\advance\pgfmath@count by-1\relax%
\ifx\pgfmath@temp\pgfmath@token@stop%
\pgfmath@error{Initial array index out of bounds.}{}%
\def\pgfmathresult{0}%
\pgfmath@smuggleone\pgfmathresult\endgroup%
\let\pgfmath@next=\relax%
\else%
\ifnum\pgfmath@count=-1\relax%
\pgfmath@count=\c@pgfmath@counta
\def\pgfmathresult{{#1}}%
\let\pgfmath@next=\pgfmathslice@@@%
\else%
\let\pgfmath@next=\pgfmathslice@@%
\fi%
\fi%
\pgfmath@next}
\def\pgfmathslice@@@#1{%
\def\pgfmath@temp{#1}%
\advance\pgfmath@count by-1\relax%
\ifnum\pgfmath@count=-1\relax%
\ifx\pgfmath@temp\pgfmath@token@stop%
\pgfmathslice@@@@\pgfmath@stop
\let\pgfmath@next=\relax%
\else%
\let\pgfmath@next=\pgfmathslice@@@@%
\fi
\else%
\ifx\pgfmath@temp\pgfmath@token@stop%
\pgfmath@error{Final array index out of bounds.}{}%
\pgfmath@smuggleone\pgfmathresult\endgroup%
\let\pgfmath@next=\relax%
\else%
\expandafter\expandafter\expandafter\def\expandafter\expandafter\expandafter\pgfmathresult\expandafter\expandafter\expandafter{\expandafter\pgfmathresult\pgfmath@csv{#1}}%
\let\pgfmath@next=\pgfmathslice@@@%
\fi%
\fi%
\pgfmath@next}
\def\pgfmathslice@@@@#1\pgfmath@stop{%
\expandafter\def\expandafter\pgfmathresult\expandafter{\expandafter{\pgfmathresult}}%
\pgfmath@smuggleone\pgfmathresult\endgroup%
}
\makeatother
\def\johnlist{2,3,5,7}
\pgfmathparse{slice({\johnlist},0,2)}
\show\pgfmathresult
\pgfmathparse{slice({\johnlist},1,2)}
\show\pgfmathresult
\pgfmathparse{slice({\johnlist},1,3)}
\show\pgfmathresult
\pgfmathparse{csvslice({\johnlist},1,2)}
\show\pgfmathresult
\let\newlist=\pgfmathresult
\pgfmathparse{\newlist[1]}
\show\pgfmathresult
\pgfmathparse{csvslice({\johnlist},1,3)}
\show\pgfmathresult
\pgfmathparse{array(slice({\johnlist},1,2),1)}
\show\pgfmathresult
\pgfmathparse{array({{3},{5}},1)}
\show\pgfmathresult
\pgfmathparse{csvslice({\johnlist},1,dim({\johnlist})-1)}
\show\pgfmathresult
\begin{document}
\begin{tikzpicture}
\node[shape=circle,draw=black] at ({\johnlist}[0],0)
{\pgfmathparse{{\johnlist}[0]}\pgfmathresult};
\node[shape=circle,draw=black] at
({{\johnlist}[dim({\johnlist})-1]},0)
{\pgfmathparse{{\johnlist}[dim({\johnlist})-1]}\pgfmathresult};
\foreach[evaluate=\x as \x using {{\johnlist}[\x]}] \x in {1,...,\len}
\node[draw=red] at (\x,0) {\x};
\end{tikzpicture}
\end{document}
(Did I mention that I think you should use LaTeX3 for this?)