25

I want to use a \foreach construct to generate several pairs of nodes, except for one of them I want to do something different. This is what I tried:

\begin{tikzpicture}[dot/.style={fill,circle,inner sep=1.5pt}]
    \foreach \x/\nm/\lbl in {0/na1/$\lnot a_1$, 1/na2/$\lnot a_2$, 2/na3/$\lnot a_3$, 3/dots/$\cdots$, 4/nan/$\lnot a_n$}
    \draw (\x,0) \if\nm{dots}\else node[dot](\nm){}\fi node[left=2pt]{\lbl};
\end{tikzpicture}

This compiles just fine, but the "dots" node still has a dot next to it. How can I do this?

(Also, are there any better ways to have circle nodes which are named? using circle(name) didn't seem to work, so I'm just using node[circle](name).)

3 Answers 3

20

When you do

\if\nm{dots}\else node[dot](\nm){}\fi

what happens is that TeX expands \nm and compares the two unexpandable tokens it finds; in the first cycle \nm is na1, so what happens is

\if na1{dots}\else node[dot](\nm){}\fi

and, since n and a are different, the "else" branch is followed. The same happens when \nm is dots: d and o are different.

What you need is a different test:

\begin{tikzpicture}[dot/.style={fill,circle,inner sep=1.5pt}]
  \def\test{dots}
  \foreach \x/\nm/\lbl in {0/na1/$\lnot a_1$, 1/na2/$\lnot a_2$, 2/na3/$\lnot a_3$, 3/dots/$\cdots$, 4/nan/$\lnot a_n$}
  \draw (\x,0) \ifx\nm\test\else node[dot](\nm){}\fi node[left=2pt]{\lbl};
\end{tikzpicture}

so TeX will compare the meaning of \nm with the meaning of \test

Another test that can work and doesn't require defining \test is

\ifnum\pdfstrcmp{\nm}{dots}=0 \else node[dot](\nm){}\fi

It has a limitation: you need pdflatex for it to work. If you plan using the code with XeLaTeX or LuaLaTeX, then say in the preamble

\usepackage{pdftexcmds}
\makeatletter
\let\unistrcmp\pdf@strcmp
\makeatother

and use \unistrcmp instead of \pdfstrcmp.

The reason is that XeTeX provides the command under the name \strcmp and LuaTeX doesn't provide it at all. The package defines \pdf@strcmp to be \pdfstrcmp if the engine is pdfTeX, \strcmp if the engine is XeTeX, and defines a Lua function in case the engine is LuaTeX. But the name has @ in it, so we provide an @-free version.

1
  • Great, thanks! Is there any way to do this inline (without requiring \test)?
    – jtbandes
    Feb 26, 2012 at 23:14
25

You could use the xifthen package:

\documentclass[parskip]{scrartcl}
\usepackage[margin=15mm]{geometry}
\usepackage{tikz}
\usepackage{xifthen}

\begin{document}

\begin{tikzpicture}

\foreach \x in {1,...,10}
{ \node[circle,draw] (\x 1) at (0,\x) {\x};
    \node[circle,draw] (\x 2)at (2,\x) {\x};
    \ifthenelse{\NOT 4 = \x \AND \NOT 7 = \x}{\draw (\x 1) -- (\x 2);}{}
}

\end{tikzpicture}

\end{document}

The exaple means if x is not four and also its not 7, then draw a line, and the output:

enter image description here

1

With functional package, we can rewrite the answer of Tom Bombadil as follows:

\documentclass[parskip]{scrartcl}
\usepackage[margin=15mm]{geometry}
\usepackage{tikz}
\usepackage{functional}
\begin{document}

\begin{tikzpicture}
\IntStepInline{1}{1}{10}{
  \node[circle,draw] (#1 1) at (0,#1) {#1};
  \node[circle,draw] (#1 2) at (2,#1) {#1};
  \BoolVarOrTF{\IntCompare{4}={#1}}{\IntCompare{7}={#1}}{}{
    \draw (#1 1) -- (#1 2);
  }
}
\end{tikzpicture}

\end{document}

You must log in to answer this question.

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