12

Apparently this question has been asked a hundred times already. But I couldn't get it to work with any of the answers provided.

I want to have nested for loops inside a Tikz matrix. Something like:

\begin{tikzpicture}[>=latex]
  \tikzstyle{every node}=[minimum size=3mm]
  \tikzset{pre/.style={draw,fill=black}}
  \matrix[matrix of math nodes,%
      left delimiter = (,%
      right delimiter = )] {%
    \foreach \i in {0,..,10} {%
      \foreach \j in {0,1} {%
        \node[pre](pre\i\j){}; &
      }
      \\
    }
  }
\end{tikzpicture}

Thanks to this and a couple of other posts I know that this cannot work.

So, I tried to translate it accordingly. But I cannot even get it to work with a simple non-nested loop:

\begin{tikzpicture}[>=latex]
  \tikzstyle{every node}=[minimum size=3mm]
  \tikzset{pre/.style={draw,fill=black}}
  \let\mymatrixcontent\empty
  \foreach \i in {0,1,2,3,4} {%
    \expandafter\gappto\expandafter\mymatrixcontent\expandafter{\i \&}%
  }
  \expandafter\gappto\expandafter\mymatrixcontent\expandafter{\\}%

  \matrix[matrix of math nodes,%
      nodes = {pre},%
      left delimiter = (,%
      right delimiter = ),
      ampersand replacement=\&] {%
    \mymatrixcontent
  };
\end{tikzpicture}

Latex fails with the extremely helpful message

! Missing } inserted.
<inserted text> 
                }
l.345 \end{tikzpicture}

What am I doing wrong? Is there an easier way to accomplish this?

Cheers!

Lemming
  • 295

2 Answers2

13

You shouldn't expand the \\ that you add to your matrix content. If you use \gappto\mymatrixcontent{\\}% (instead of \expandafter\gappto\expandafter\mymatrixcontent\expandafter{\\}%), your example works:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{matrix}
\usepackage{etoolbox}


\begin{document}
\begin{tikzpicture}[>=latex]
  \tikzstyle{every node}=[minimum size=3mm]
  \tikzset{pre/.style={draw,fill=black,text=white}}
  \let\mymatrixcontent\empty
  \foreach \i in {0,1,2,3,4} {%
    \expandafter\gappto\expandafter\mymatrixcontent\expandafter{\i \&}%
  }
  \gappto\mymatrixcontent{\\}%

  \matrix[matrix of math nodes,%
      nodes = {pre},%
      left delimiter = (,%
      right delimiter = ),
      ampersand replacement=\&] {%
    \mymatrixcontent
  };
\end{tikzpicture}
\end{document} 
egreg
  • 1,121,712
Jake
  • 232,450
12

The nested version looks like:

\documentclass{article}
\usepackage{etoolbox}
\usepackage{tikz}
\usetikzlibrary{matrix}

\begin{document}
\let\mymatrixcontent\empty
\newcommand{\row}{%
  \foreach \j in {1,...,10}{
    \foreach \i in {1,2} {%
      \begingroup\edef\x{\endgroup
         \noexpand\gappto\noexpand\mymatrixcontent{ pre-\i-\j \&}}\x
      }%
    \gappto\mymatrixcontent{\\}%
  }
}
\row

\begin{tikzpicture}
\tikzset{every node/.style={minimum size=3mm},
  pre/.style={draw,fill=yellow}}

  \matrix (a) [ampersand replacement=\&,matrix of math nodes, nodes={pre}]{
    \mymatrixcontent
  };
\end{tikzpicture}

\end{document}

enter image description here

percusse
  • 157,807
  • Apparently I got the row-column labels in the wrong order – percusse Jun 19 '12 at 14:12
  • Thanks, that is exactly what I was looking for. This is the first time that I got to tinker with expandafter/noexpand and all the like. Do you know a good introduction on that topic? I don't quite get how the begin-/endgroup part works. The idea is to not overwrite any already existing \x? – Lemming Jun 25 '12 at 17:29
  • Okay, it is almost what I'm looking for. I would like to set tikz-node-labels. \node[pre](p\i\j){content}. So I inserted \noexpand\node[pre](p\i\j){content} in place of pre-\i-\j. Unfortunately, LaTeX seems to loop infinitely long on that. When I ctrl-C out, It is somewhere inside \pgf@matrix@singal@cell@end. How can I put a \node command in there? – Lemming Jun 25 '12 at 17:55
  • @Lemming What is content? It will make all the entries content. Also I've used matrix of nodes option so they are already nodes you don't need to add node to the syntax/ – percusse Jun 25 '12 at 19:54
  • Sorry, I should have been more clear on what I want here. The purpose is to have different node types within that matrix. So I would have, say, five rows of one type and then two rows of another type. Hence, the explicit \node command. content would most likely be empty, so that it's just a white, or grey box. Additionally, I would like to be able to connect some of those boxes with arrows. Hence, the labels (p\i\j). So far I've been more of a latex user, than a programmer. Do you know a good introduction on these things? – Lemming Jun 26 '12 at 11:17
  • @Lemming Excuse my ignorance but I still don't see the connection between this quesiton and your comments. If you have customization problems then you have to divide the parts in foreach loops because you cannot modify the loop in the middle. Once it is set then it is valid for the whole loop. PGF/TikZ manual is always helpful and that's what I have started with. However I also think that you might ask a genuine question with an image of you wish to obtain and a minimal code without the automation such that people here can offer simplifications. – percusse Jun 26 '12 at 11:27
  • My bad. The issue was nothing but a missing semicolon after the node command. Now your solution works perfectly fine. The pgfmanual is a good resource in general. However, I couldn't find anything helpful about foreach in matrices in it. E.g. no mention of \gappto in it. – Lemming Jun 26 '12 at 14:47
  • @Lemming That's becuase we are mixing content of etoolbox and tikz. Normally you don't need such tricks. – percusse Jun 26 '12 at 19:04