TikZ 是否提供了一种简洁的方法来测试指定集合的​​成员资格?

TikZ 是否提供了一种简洁的方法来测试指定集合的​​成员资格?

TikZ 是否提供了一种合理的原生/简洁的方式来表达“如果循环变量是该集合的一个元素,那么......”?

评论。 我要求的一个例子是伪代码

 \pgfmathparse{\index in {0,2,4,6,8}} 

当然,当且仅当 \index==0 或 \index==2 或 \index==4 或 \index==6 或 \index==8 在其他非伪代码中时,其结果才应为布尔值 1

\documentclass{article}

\usepackage{tikz}
\usepackage{ifthen}

\begin{document}

\begin{tikzpicture}
    \foreach \index in {0,1,...,101}{
        \ifthenelse{
            \pgfmathparse{\index in {0,2,4,6,8}} % <-
        }{
            \node (v\index) at (\index cm,\index cm) {$\index$};
        }{
        };
    }
\end{tikzpicture}

\end{document}
  • 编写一个循环,将 {0,2,4,6,8} 直接硬连线为其循环变量的范围,这对我来说不是一个选择,因为上面只是我需要这个应用程序的一个小说明性示例,它有一个大的外循环,然后需要几个形式为“如果循环变量在这个集合中,则执行此操作”的 if 条件,其中出现了几个完全不同的“这个集合”。

  • 简而言之,我需要根据形式为“循环变量是否在指定集合中”的查询的布尔值来控制循环。

  • 当然,你可以写一个很长的逻辑或相等测试,分别比较\index0、2、4、6、8。如果能写得更简洁一些就更好了。我在手册里没找到。

答案1

这是一个简单的解决方案。但您必须先声明并命名您的集合。

\documentclass{article}

\usepackage{etoolbox}
\usepackage{tikz}
\tikzset{
  def set elem/.code 2 args={\csdef{@sets@#1@#2}{}{}},
  def set/.style 2 args={
    def elem in@#1/.style={def set elem={#1}{##1}},
    def elem in@#1/.list={#2},
  }
}
\def\ifinset#1#2{\ifcsdef{@sets@#1@#2}}

\begin{document}
\tikzset{def set={myset}{2,4,6}}
\foreach \myval in {1,...,10}{
  \ifinset{myset}{\myval}{\myval{} in set\par}{\myval{} not in set\par}
}
\end{document}

结果:

1 not in set
2 in set
3 not in set
4 in set
5 not in set
6 in set
7 not in set
8 not in set
9 not in set
10 not in set

答案2

TikZ 不提供某项是否在列表中的测试。使用 PGF 宏也无法实现此测试,因为\foreach它不完全可扩展。

这是一个使用 Lua 来实现这个功能的方法。

\documentclass{article}

\usepackage{tikz}
\usepackage{ifthen}

\directlua{
function has_value(t,v)
    for _,e in ipairs(t) do
        if e == v then
            tex.sprint("\noexpand\\boolean{true}")
            return
        end
    end
    tex.sprint("\noexpand\\boolean{false}")
end
}

\def\ifinset#1#2{\directlua{has_value({#1},#2)}}

\begin{document}

\begin{tikzpicture}
  \foreach \index in {0,1,...,101}{
    \ifthenelse{
      \ifinset{0,2,4,6,8}{\index}
    }{
      \node (v\index) at (\index cm,\index cm) {$\index$};
    }{
    };
  }
\end{tikzpicture}

\end{document}

如果您不介意循环测试集,那么在 TikZ 中也可以轻松实现。

\documentclass{article}

\usepackage{tikz}
\usepackage{ifthen}

\begin{document}

\begin{tikzpicture}
  \foreach \index in {0,1,...,101}{
    \foreach \test in {0,2,4,6,8} {
      \ifthenelse{\equal{\index}{\test}}{
        \node (v\index) at (\index cm,\index cm) {$\index$};
      }{
        % false case
      }
    }
  }
\end{tikzpicture}

\end{document}

答案3

您可以在 的帮助下做到这一点expl3; 的第二个参数\IsInTF也可以是扩展为列表的宏。

\documentclass{article}

\usepackage{tikz}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\IsInTF}{mmmm}
 {
  \clist_if_in:xxTF { #2 } { #1 } { #3 } { #4 }
 }
\prg_generate_conditional_variant:Nnn \clist_if_in:nn { xx } { T,F,TF }
\ExplSyntaxOff

\begin{document}

\begin{tikzpicture}
  \foreach \index in {0,1,...,101}{
    \IsInTF{\index}{0,2,4,8} % <-
      {\node (v\index) at (\index cm,\index cm) {$\index$};}
      {};
  }
\end{tikzpicture}

\end{document}

在此处输入图片描述

答案4

这是Paul Gaborit 的回答

如果您想使用他的代码来定义新命令,元素将仅添加到先前命令的集合中。因此,需要在使用该集合后立即再次删除元素。这可以以类似的方式完成,通过使用\cslet并将元素设置为\undefined。这是一个完整的 MWE:

\documentclass{article}

\usepackage{etoolbox}
\usepackage{tikz}
\tikzset{
  def set elem/.code 2 args={\csdef{@sets@#1@#2}{}{}},
  def set/.style 2 args={
    def elem in@#1/.style={def set elem={#1}{##1}},
    def elem in@#1/.list={#2},
  },
  % these five lines are new to undefine elements:
  undef set elem/.code 2 args={\cslet{@sets@#1@#2}{\undefined}},
  undef set/.style 2 args={
    undef elem in@#1/.style={undef set elem={#1}{##1}},
    undef elem in@#1/.list={#2},
  }
}
\def\ifinset#1#2{\ifcsdef{@sets@#1@#2}}

\newcommand{\mycommand}[1]{%
  \tikzset{def set={myset}{#1}}
  \begin{tikzpicture}[
      every node/.style={minimum size=5mm, anchor=south west, inner sep=0pt},
      scale=0.5
  ]
  \foreach \myval in {1,...,20}{
    \ifinset{myset}{\myval}{
      \node [white, fill=green, font=\sffamily\bfseries] at (\myval, 0) {\myval};
    }{
      \fill [black] (\myval, 0) rectangle ++(1, 1);
    }
  }
  \end{tikzpicture}
  \tikzset{undef set={myset}{#1}} %<< new: required to remove the numbers again
}

\begin{document}
\thispagestyle{empty}
\mycommand{2,4,6,8,10,12,14,16,18,20}\par
\mycommand{3,6,9,12,15,18}\par
\mycommand{4,8,12,16,20}\par
\mycommand{5,10,15,20}\par
\mycommand{6,12,18}\par
\mycommand{7,14}\par
\mycommand{8,16}\par
\mycommand{9,18}\par
\mycommand{10,20}\par
\end{document}

工作示例图像

相反,当您没有取消定义元素(注释掉\tikzset{undef set={myset}{#1}})时,结果如下所示:

在此处输入图片描述

相关内容