我怎样才能使这两个嵌套的 \foreach 循环工作?

我怎样才能使这两个嵌套的 \foreach 循环工作?

我尝试使用嵌套\foreach循环在许多节点之间创建边。

\documentclass{standalone}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
  \node (a) at (0, 1) {};
  \node (b) at (0, -1) {};
  \node (c) at (1, 0) {};
  \node (d) at (-1, 0) {};
  \foreach \from/\targets in {%
    b/d,%
    {a/b,c,d}%
  } {
    \typeout{\from-\targets}
    \foreach \to in {\targets} {
      \typeout{ \from-\to}
      \path (\from) edge (\to);
    }
  }
\end{tikzpicture}
\end{document}

但这失败了,出现了神秘的错误

b-d
 b-d
a-b,c,d
 a-b,c,d

! Package PGF Math Error: Unknown function `b' (in 'b').

\typeout错误显示之前所示,似乎\targets没有展开,因此解释为单个参数而不是列表。此时可以强制展开吗?或者还有其他方法可以修复它吗?

答案1

您需要从内部循环中删除括号。也就是说,您不应该将 传递{\targets}\foreach循环,而应该传递\targets

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

\begin{tikzpicture}
  \node (a) at (0, 1) {};
  \node (b) at (0, -1) {};
  \node (c) at (1, 0) {};
  \node (d) at (-1, 0) {};
  \foreach \from/\targets in {%
    b/d,%
    {a/b,c,d}%
  } {
    \typeout{\from-\targets}
    \foreach \to in \targets {
      \typeout{ \from-\to}
      \path (\from) edge (\to);
    }
  }
\end{tikzpicture}

\end{document}

在此处输入图片描述

答案2

除了问题\foreach之外,我认为语法

\path (b) edge (d)
      (a) edge (b) edge (c) edge (d);

变得更加自然。在边到边的基础上更改边缘选项也更加容易(或者也可以更改多个边缘):

\path (b) edge (d) {[thick]
      (a) edge (b) edge[green] (c) edge[red,->] (d)};

不过,类似的事情仍然可以做\foreach,比如说

\path (b) edge (d) {[thick]
      (a) \foreach \opt/\p in {/b, green/c, {red,->}/d}
                  {edge[style/.expand once=\opt] (\p)}};

和我的qrr.misc库(代码类似于我的另一个答案)可以做到

\path (b) edge (d) {[thick]
      (a) [edges to={b,[green] c, [{red,->}] d}]};

应该注意的是,,选项中的 必须以某种方式受到保护,要么采用所示方式,要么通过{[red, ->] d},即将整个内容括在括号中。(这可以使其更强大,或者可以更改为使用()来围绕坐标,而不是使用,,但实现将需要更多解析。)

代码

\documentclass[tikz]{standalone}
\usetikzlibrary{qrr.misc}
\begin{document}
\begin{tikzpicture}
  \node (a) at (0, 1) {};  \node (b) at (0, -1) {};
  \node (c) at (1, 0) {};  \node (d) at (-1, 0) {};
  \path (b) edge (d) {[thick]
        (a) edge (b) edge[green] (c) edge[red,->] (d)};
\end{tikzpicture}
\begin{tikzpicture}
  \node (a) at (0, 1) {};  \node (b) at (0, -1) {};
  \node (c) at (1, 0) {};  \node (d) at (-1, 0) {};
  \path (b) edge (d) {[thick]
        (a) \foreach \opt/\p in {/b, green/c, {red,->}/d}
                    {edge[style/.expand once=\opt] (\p)}};
\end{tikzpicture}
\begin{tikzpicture}
  \node (a) at (0, 1) {};  \node (b) at (0, -1) {};
  \node (c) at (1, 0) {};  \node (d) at (-1, 0) {};
  \path (b) edge (d) {[thick]
        (a) [edges to={b,[green] c, [{red,->}] d}]};
\end{tikzpicture}
\end{document}

输出

在此处输入图片描述

答案3

重要的是在指定要处理的列表中的元素的方式要保持一致\foreach

在下面的方法中,我发现这种方法更直观,在外循环的第一次迭代中\targets扩展到,在第二次迭代中扩展到。因此,为内循环指定的方法可以按预期工作。{b}{b,c,d}\foreach \to in \targets

在此处输入图片描述

\documentclass{standalone}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
  \node (a) at (0, 1) {};
  \node (b) at (0, -1) {};
  \node (c) at (1, 0) {};
  \node (d) at (-1, 0) {};
  \foreach \from/\targets in {b/{d},a/{b,c,d}}
  {%
    \typeout{\from-\targets}
    \foreach \to in \targets
    {%
        \typeout{ \from-\to}
      \path (\from) edge (\to);
    }
  }
\end{tikzpicture}
\end{document}

相关内容