5

I need to draw many nodes with labels that I can calculate from their indices. However, a small amount of them do not follow the rule, thus I need to assign their labels manually. Can I do that somehow?

MWE:

\documentclass[tikz,border=3.14mm]{standalone}
\usepackage{amssymb}
\begin{document}
\begin{tikzpicture}
    \foreach \i in {1,...,30}
    {
        \node at (\i,0) [rectangle,label=above:\i] (v\i) {$i$};
    }
    % here I want to make the label of node v7 to become $\varnothing$
\end{tikzpicture}
\end{document}

Note: this has nothing to do with animation, I just want to create the nodes in a loop and then change labels for some of them.

UPD: I corrected MWE, as the original one was not exactly what I implied.

2 Answers 2

9

You can use \node also, which is described on p. 250 of the pgfmanual, for that.

\documentclass[tikz,border=3.14mm]{standalone}
\usepackage{amssymb}
\begin{document}
\begin{tikzpicture}
    \foreach \i in {1,...,10}
    {
        \node at (\i,0) [rectangle,label={above:$ \i $}] (v\i) {$i$};
    }
    \foreach \i in {3,6,8}{
        \node also [label={[fill=white]above:$ \varnothing $}] (v\i);
    }
\end{tikzpicture}
\end{document}

enter image description here

BIG THANKS TO MAX for the edit.

Just in case you ever have wider labels: give the labels names and use their width for Max' fill=white trick.

\documentclass[tikz,border=3.14mm]{standalone}
\usetikzlibrary{calc}
\usepackage{amssymb}
\begin{document}
\begin{tikzpicture}
    \foreach \i in {1,2,...,10}
    {
        \node at (\i,0) [rectangle,label={[name=lab\i]above:$\i\i$}] (v\i) {$i$};
    }
    \foreach \i in {3,6,10}{
        \path let \p1=($(lab\i.north east)-(lab\i.south west)$) in node also 
        [label={[fill=white,minimum width=\x1,minimum height=\y1]above:$ \varnothing $}] (v\i);
    }
\end{tikzpicture}
\end{document}

ADDENDUM: Just for curiosity I was wondering if there is a simple way to make Max' nice answer work with lists. I am sure there is and leave it to others to use some xparse or other magic. Here I just want to report an irony of fate. If one goes for the built-in LaTeX check whether or not something is an element of a list, then my naive attempt fails for two digits, precisely where the simplest version of the above also starts to go wrong. Rather funny and ironic, I'd say. ;-)

\documentclass[tikz]{standalone}
\makeatletter
% https://tex.stackexchange.com/a/260921/121799 and https://tex.stackexchange.com/a/287094/121799
\newcommand\ifmember[2]{% 
\in@{#1}{#2}%
\ifin@
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
}
\makeatother
\usepackage{amssymb}

\begin{document}

\begin{tikzpicture}
    \foreach \i in {1,...,10}
    {   
        \edef\temp{\noexpand\ifmember{\i}{3,6,9}{\varnothing}{\i}}
        \node at (\i,0) [rectangle,label=above:$\temp$] (v\i) {$ i $};
    }
\end{tikzpicture}
\end{document}
9
  • Perhaps, my MWE was not exactly what I meant. I assumed that every node got a label in a loop, and then I want to change it. I.e. it is \node at (\i,0) [rectangle,label=above:\i] (v\i) {$i$}; If I try to do that with \node also I end up with two labels, one over another. Aug 13, 2018 at 12:31
  • I updated MWE to reflect what I mean. Aug 13, 2018 at 12:36
  • 2
    @YauhenYakimenka You could of course do label={[fill=white]above:$\varnothing$}, then you wouldn't see the underlying label. That would be simpler than my answer if you have some more different labels.
    – Max
    Aug 13, 2018 at 12:50
  • 1
    @marmot I took the liberty of editing your answer, if you don't agree, please roll it back or edit it further.
    – Max
    Aug 13, 2018 at 13:36
  • 1
    @Max I actually think the conditionals in the loop are cleaner. If one were to replace the label 10, there would be some leftover. Why don't you undelete your nice answer? (Having said this, I also realize that one could make the \node also work then by giving the labels also names and then using their width.)
    – user121799
    Aug 13, 2018 at 16:22
4

You can use conditionals inside the \foreach loop:

\documentclass[tikz]{standalone}

\usepackage{amssymb}

\begin{document}
\begin{tikzpicture}
    \foreach \i in {1,...,10}
    {
        \ifnum\i=7
            \node at (\i,0) [rectangle,label=above:$ \varnothing $] (v\i) {$ i $};
        \else
            \node at (\i,0) [rectangle,label=above:$ \i $] (v\i) {$ i $};
        \fi
    }
    % here I want to make the label of node v7 to become $\varnothing$
\end{tikzpicture}
\end{document}

enter image description here

If you have more labels that should be different, the code stays more readable if you use \pgfmathparse to do check the conditional:

\documentclass[tikz,border=3.14mm]{standalone}
\usepackage{amssymb}
\begin{document}
\begin{tikzpicture}
    \foreach \i in {1,2,...,10}
    {
        \pgfmathparse{
            ifthenelse(\i==3,
                "varnothing",
                ifthenelse(\i==7,
                    "varnothing",
                    ifthenelse(\i==10,
                        "varnothing",
                        "i"
                    )
                )
            )
        }
        \def\myLabel{\csname\pgfmathresult\endcsname}
        \node at (\i,0) [rectangle,label={above:$ \myLabel $}] (v\i) {$i$};
    }
\end{tikzpicture}
\end{document}

enter image description here

You must log in to answer this question.

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