tikz 并行 foreach

tikz 并行 foreach

我已经看到了解决方案这个帖子

\pgfset{
  foreach/parallel foreach/.style args={#1in#2via#3}{evaluate=#3 as #1 using {{#2}[#3-1]}},
}

但有一个错误:当所有列表都只有一个项目时,它不会按预期工作。原因是这个帖子

因此我尝试引入 latex3 以使其无错误。

\documentclass[tikz, border=1cm]{standalone}
\usepackage{xparse}
\ExplSyntaxOn
\clist_new:N \g_list_clist
\NewDocumentCommand {\getitem} {m O{1}} {
  \clist_gset:Nn \g_list_clist #1
  \clist_item:Nn \g_list_clist {#2}
}
\ExplSyntaxOff
\pgfset{
  foreach/parallel foreach/.style args={#1in#2via#3}{
    evaluate=#3 as #1 using "before\getitem{#2}[#3]"
  },
}

\begin{document}
\begin{tikzpicture}
  \foreach \i [
    count = \c,
    parallel foreach = \x in {test} via \c,
  ] in {1}
    \node at (\i, 0) {blank\x};
  \node at (1, -1) {no blank\getitem{{test}}[1]};
\end{tikzpicture}
\end{document}

但有一个小问题:这样获得的物品有额外的空格在它之前。如何解决这个问题?为什么#1不需要支撑? 在此处输入图片描述

答案1

您定义parallel foreach为具有参数文本的样式#1in#2via#3,没有空格,然后使用:

parallel foreach = \x in {test} via \c

因此的参数为parallel foreach␣\x␣␣{test}␣␣\c然后当您将其传递给时\getitem,您将得到:

\clist_gset:Nn\g_list_clist␣{test}␣

在抓取第二个参数时,TeX 会使用第一个空格标记\clist_gset:Nn,但第二个空格会在您的节点中排版。

这里有几种可能性,例如\tl_trim_spaces:n

\clist_gset:Nx \g_list_clist { \tl_trim_spaces:n {#1} }

(实际上,实现起来要复杂一些,需要检查 参数周围的括号parallel foreach;请参见此答案底部的代码)。但是expl3提供了\clist_item:nn,因此您可以从逗号分隔的列表中获取项目,而无需将其存储在变量中,这使得这里的事情变得更简单:

\exp_args:Nx \clist_item:nn
  { \tl_trim_spaces:n {#1} } {#2}

虽然由于有额外的括号,这无法处理列表中存在多个项目的可能性。您需要检查参数是否parallel foreach在括号内,如果是,则将其删除,如下所示:

\NewDocumentCommand {\getitem} {m O{1}} {
  \exp_args:Nx \clist_item:nn
    { \tl_trim_spaces_apply:nN {#1} \zhiyuan_remove_braces:n } {#2}
}
\cs_new:Npn \zhiyuan_remove_braces:n #1
  {
    \tl_if_head_is_group:nTF {#1}
      { \exp_not:n #1 }
      { \exp_not:n {#1} }
  }

这样,您的代码就会产生预期的输出:

在此处输入图片描述

\documentclass[tikz, border=1cm]{standalone}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand {\getitem} {m O{1}} {
  \exp_args:Nx \clist_item:nn
    { \tl_trim_spaces_apply:nN {#1} \zhiyuan_remove_braces:n } {#2}
}
\cs_new:Npn \zhiyuan_remove_braces:n #1
  {
    \tl_if_head_is_group:nTF {#1}
      { \exp_not:n #1 }
      { \exp_not:n {#1} }
  }
\ExplSyntaxOff
\pgfset{
  foreach/parallel foreach/.style args={#1in#2via#3}{
    evaluate=#3 as #1 using "before\getitem{#2}[#3]"
  },
}

\begin{document}
\begin{tikzpicture}
  \foreach \i [
    count = \c,
    parallel foreach = \x in {test,another} via \c,
  ] in {1,2}
    \node at (1, \i) {blank\x};
    \node at (1, -1) {no blank\getitem{{test}}[1]};
\end{tikzpicture}
\end{document}

clist下面是使用变量而不是的代码\clist_item:nn

\documentclass[tikz, border=1cm]{standalone}
\usepackage{xparse}
\ExplSyntaxOn
\clist_new:N \g_list_clist
\NewDocumentCommand {\getitem} {m O{1}} {
  \use:x
    {
      \clist_gset:Nx \exp_not:N \g_list_clist
        { \tl_trim_spaces_apply:nN {#1} \zhiyuan_remove_braces:n }
    }
  \clist_item:Nn \g_list_clist {#2}
}
\cs_new:Npn \zhiyuan_remove_braces:n #1
  {
    \tl_if_head_is_group:nTF {#1}
      { \exp_not:n #1 }
      { \exp_not:n {#1} }
  }
\ExplSyntaxOff
\pgfset{
  foreach/parallel foreach/.style args={#1in#2via#3}{
    evaluate=#3 as #1 using "before\getitem{#2}[#3]"
  },
}

\begin{document}
\begin{tikzpicture}
  \foreach \i [
    count = \c,
    parallel foreach = \x in {test,another} via \c,
  ] in {1,2}
    \node at (1, \i) {blank\x};
    \node at (1, -1) {no blank\getitem{{test}}[1]};
\end{tikzpicture}
\end{document}

相关内容