PGF foreach:处理空列表的优雅方法

PGF foreach:处理空列表的优雅方法

我正在beamer使用编写一个简单的动画tikz。代码如下

\documentclass{beamer}
\usepackage{tikz}
\usetikzlibrary{positioning}

\begin{document}

\begin{frame}[fragile]\relax
\foreach \i in {0,...,3}{
\only<+>{
    \begin{tikzpicture}[node distance=.3]
        \node[circle,draw](x0){$x_0$};
        \foreach\x [remember=\x as \px (initially 0)] in {1,...,\i}{
            \node[draw, right=of x\px](P\x){$P[x_{\px}, x_{\x}]$};
            \node[circle,draw, right=of P\x](x\x){$x_{\x}$};
            \draw (P\x) edge (x\px) edge (x\x);
        }
        \node[draw, right=of x\i] (L) {$L[x_{\i}]$};
        \draw (L) edge (x\i) ;
    \end{tikzpicture}
}}
\end{frame}

\end{document}

如您所见,外层 foreach 从 开始\i=0;内层 foreach 循环遍历一个列表{1,...,\i},该列表在外层 for 的第一次迭代中重写为{1,...,0}。现在,内层 for 的列表在第一次迭代中的预期语义是空列表,但PGF将其解释为{1,0},这在我的示例中生成了错误的图像。有点令人惊讶的{1,2,...,0}是 被视为{1,2}

我通过提取外循环之外的第一次迭代解决了这个问题,但我想知道:是否有更优雅的解决方案?

答案1

您可以使用包xifthen。它提供了一个名为的函数\ifthenelse{<if-clause>}{then-code}{else-code}。在上面调用\foreach-loop之前,会测试您的\i-counter是否大于0。如果是,0则不会运行任何代码(空else-code)。如果它更大,则\foreach执行您的-loop。

希望这可以帮助

\documentclass{beamer}
\usepackage{tikz}
\usetikzlibrary{positioning}

% Use package xifthen
\usepackage{xifthen}

\begin{document}
\begin{frame}[fragile]\relax
\foreach \i in {0,...,3}{
\only<+>{
 \begin{tikzpicture}[node distance=.3]
  \node[circle,draw](x0){$x_0$};
   \ifthenelse{\i > 0}{ % Check if \i bigger than 0, if true then run
    \foreach\x [remember=\x as \px (initially 0)] in {1,...,\i}{
     \node[draw, right=of x\px](P\x){$P[x_{\px}, x_{\x}]$};
     \node[circle,draw, right=of P\x](x\x){$x_{\x}$};
     \draw (P\x) edge (x\px) edge (x\x);
    }
   }{}; % Else run nothing
  \node[draw, right=of x\i] (L) {$L[x_{\i}]$};
  \draw (L) edge (x\i) ;
 \end{tikzpicture}
 }}
\end{frame}
\end{document}

编辑:正如 percusse 在他的评论中所述,检查\i > 0也可以由内部人员完成,而无需使用额外的库(如 xifthen)。例如\ifnum

\documentclass{beamer}
\usepackage{tikz}
\usetikzlibrary{positioning}

\begin{document}
\begin{frame}[fragile]\relax
\foreach \i in {0,...,3}{
\only<+>{
 \begin{tikzpicture}[node distance=.3]
  \node[circle,draw](x0){$x_0$};
   \ifnum\i>0 % Check if \i bigger than 0 and if true run the \foreach
    \foreach\x [remember=\x as \px (initially 0)] in {1,...,\i}{
     \node[draw, right=of x\px](P\x){$P[x_{\px}, x_{\x}]$};
     \node[circle,draw, right=of P\x](x\x){$x_{\x}$};
     \draw (P\x) edge (x\px) edge (x\x);
    }
    \fi % End if-clause
  \node[draw, right=of x\i] (L) {$L[x_{\i}]$};
  \draw (L) edge (x\i) ;
 \end{tikzpicture}
 }}
\end{frame}
\end{document}

相关内容