# Tikz: deal with exceptions within loops

I am a fan of \foreach loops in tikz, but often find myself in a situation where I want to make an exception for a single iteration of the loop. For example,

  \documentclass{article}
\usepackage{tikz}
\begin{document}

\begin{tikzpicture}[every node/.style={draw, circle}]
\node[label=above:a] (a) at (3,1) {};
\node[label=below:b] (b) at (3,-1) {};

\foreach \i in {0,1,2,3,4,5,6} {
\node[label=above:\i] (x\i) at (\i, 0) {};
\draw (x\i)--(b);
}
\draw (a)--(x3);
\end{tikzpicture}

\end{document}


I would like to have label=right:\i for node 3 since otherwise it intersects the edge to a. I can think of some ugly solutions (e.g., taking this case out of the loop and copying the code with the difference for it alone), but do you have any nicer way to achieve this?

-

You are looking for the \ifnum<condition> \else \fi construct. See the code below.

Note that by \ifnum you can only compare integers. More complex conditions can be done using e.g. \pgfmathparse.

\documentclass{article}
\usepackage{tikz}
\begin{document}

\begin{tikzpicture}[every node/.style={draw, circle}]
\node[label=above:a] (a) at (3,1) {};
\node[label=below:b] (b) at (3,-1) {};

\foreach \i in {0,...,6} {
\ifnum\i=3
\node[label=right:\i] (x\i) at (\i, 0) {};
\else
\node[label=above:\i] (x\i) at (\i, 0) {};
\fi
\draw (x\i)--(b);
}
\draw (a)--(x3);
\end{tikzpicture}

\end{document}


Edit: To avoid copying a possibly extensive code within the \ifnum \else \fi construct, you can do for example this. I'm not 100% sure this is robust but here it works.

\documentclass{article}
\usepackage{tikz}
\begin{document}

\begin{tikzpicture}[every node/.style={draw, circle}]
\node[label=above:a] (a) at (3,1) {};
\node[label=below:b] (b) at (3,-1) {};

\foreach \i in {0,...,6} {
\ifnum\i=3 \def\location{right} \else \def\location{above} \fi  % change here
\node [label=\location:\i] (x\i) at (\i, 0) {};                 % and here
\draw (x\i)--(b);
}
\draw (a)--(x3);
\end{tikzpicture}

\end{document}

-
Nice! Is there a way to make this inline? I've just tried \node[\ifnum\i=3 label=right:\i \else label=above:\i\fi] (x\i) at (\i, 0) {};, without success. – tarulen Feb 22 at 15:18
Not quite as far as I know, but there are other options. I'll edit the answer. – Ondrian Feb 22 at 15:24

You can define your label option like this:

[label={\ifnum\i\equals3 right\else above\fi :\i}]

with the command \newcommand\equals{=} added to the preamble. Because this = is what cases a parse error for tikz when it tries to split the input at = to recognize key/value pairs. This idea was borrowed from a comment by @egreg on a similar question.

\documentclass[border=5pt,tikz]{standalone}
\newcommand\equals{=}
\begin{document}

\begin{tikzpicture}[every node/.style={draw, circle}]
\node[label=above:a] (a) at (3,1) {};
\node[label=below:b] (b) at (3,-1) {};

\foreach \i in {0,...,6} {
\node [label={\ifnum\i\equals3 right\else above\fi :\i}] (x\i) at (\i, 0) {};
\draw (x\i)--(b);
}
\draw (a)--(x3);
\end{tikzpicture}

\end{document}


-
That's a cool hack :) – Ondrian Feb 22 at 17:20
Thank you, you've provided a nice solution too. – AboAmmar Feb 22 at 21:07

First solution (remove exception case from \foreach list):

\documentclass{standalone}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}[every node/.style={draw, circle}]
\node[label=above:a] (a) at (3,1) {};
\node[label=below:b] (b) at (3,-1) {};

\foreach \i in {0,1,2,4,5,6} {
\node[label=above:\i] (x\i) at (\i, 0) {};
\draw (x\i)--(b);
}
% exception
\node[label=right:3] (x3) at (3, 0) {};
\draw (x3)--(b);

\draw (a)--(x3);
\end{tikzpicture}
\end{document}


Second solution (no exception using two variables in \foreach):

\documentclass{standalone}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}[every node/.style={draw, circle}]
\node[label=above:a] (a) at (3,1) {};
\node[label=below:b] (b) at (3,-1) {};

\foreach \i/\mypos in {0/above,1/above,2/above,3/right,4/above,5/above,6/above} {
\node[label=\mypos:\i] (x\i) at (\i, 0) {};
\draw (x\i)--(b);
}

\draw (a)--(x3);
\end{tikzpicture}
\end{document}

-