\in@ 的语法并使用宏作为参数

\in@ 的语法并使用宏作为参数

我尝试让命令在文档的开头接受逗号分隔的列表,然后稍后测试给定的逗号分隔列表以查看它是否包含(完全相同)的元素。因此;

\documentclass{article}
\usepackage{etoolbox}
\makeatletter
\newcommand{\activetags}{yellow, blue, red, green}
\newif\ifis@Strict
\is@Stricttrue

\newcommand{\strictTest}[1]
    {
    \renewcommand*{\do}[1]
        {
        \in@{##1}{\activetags}
            \ifin@{}% If the element is in the second string do nothing
            \else
            \is@Strictfalse% If you find a non fitting string, mark strict as false.
            \fi
        }
    }

\newcommand{\filter}[1]{
\strictTest{#1}{\activetags}%  Check one being subset of the other
\docsvlist{#1}
\strictTest{\activetags}{#1}% Check other being subset of the one
\docsvlist{\activetags}
\ifis@Strict{The elements match!}\else{The elements don't match}\fi
\is@Stricttrue
}


\begin{document}

\filter{yellow, blue, red, green}% This should show "The elements match!"
\filter{yellow, blue, red}% This should show "The elements don't match"
\filter{yellow, blue, red, green, purple}% This should show "The elements don't match"

\ifis@Strict{It works}\else{It failed}\fi% This should show "It works"

\end{document}

我似乎在任何地方都找不到有关语法的任何信息\in@。据我所知,它需要 2 个参数并测试其中一个参数以查看它是否包含在另一个子字符串中。这似乎可以满足我的需要,但我似乎无法让宏在其中展开。

如果我硬连线命令,宏似乎可以工作\activetags,但我似乎无法\expandafter正确地工作,而且我所知道的任何命令\edef\let命令也无法提前扩展令牌......

我可能只是错过了一些愚蠢的东西,但现在已经尝试了几个小时了......

谢谢

答案1

\in@不对其参数进行扩展;如果您想要它,您必须自己做。

\documentclass{article}
\usepackage{etoolbox}

\makeatletter
\newif\ifis@Strict
\is@Stricttrue

\newcommand{\strictTest}[1]{%
  \renewcommand*{\do}[1]{%
    \begingroup\edef\x{\endgroup\noexpand\in@{##1}{\activetags}}\x
    \ifin@
      % If the element is in the second string do nothing
    \else
      \is@Strictfalse% If you find a non fitting string, mark strict as false.
    \fi
  }%
}

\newcommand{\filter}[1]{%
  \strictTest{#1}{\activetags}%  Check one being subset of the other
  \docsvlist{#1} % here we want a space
  \strictTest{\activetags}{#1}% Check other being subset of the one
  \docsvlist{\activetags} % here we want a space
  \ifis@Strict
    The elements match!%
  \else
    The elements don't match%
  \fi
  \is@Stricttrue
}
\makeatother

\newcommand{\activetags}{yellow, blue, red, green}


\begin{document}

\filter{yellow, blue, red, green}% This should show "The elements match!"

\filter{yellow, blue, red}% This should show "The elements don't match"

\filter{yellow, blue, red, green, purple}% This should show "The elements don't match"

%\ifis@Strict{It works}\else{It failed}\fi% This should show "It works"

\end{document}

我已经重新格式化了代码,以避免输出中出现虚假空格。

但是,你到底想要什么,这一点并不十分清楚。测试

\filter{green, yellow, blue, red}

将返回 false。没有逐项比较。


这里有一个实现,expl3它逐项比较两个列表,如果两个列表项一致,即使顺序不同,也返回 true。

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\clist_new:N \l_jason_active_list_clist
\bool_new:N \l_jason_strict_bool

\cs_new_protected:Nn \jason_strict_test:n
 {
  \bool_set_true:N \l_jason_strict_bool
  % check whether the input items are in the fixed list
  \clist_map_inline:nn { #1 }
   {
    \clist_if_in:NnF \l_jason_active_list_clist { ##1 }
     { \bool_set_false:N \l_jason_strict_bool }
   }
  % check whether the fixed items are in the input list
  \clist_map_inline:Nn \l_jason_active_list_clist
   {
    \clist_if_in:nnF { #1 } { ##1 }
     { \bool_set_false:N \l_jason_strict_bool }
   }
 }

\NewDocumentCommand{\setactivelist}{m}
 {
  \clist_set:Nn \l_jason_active_list_clist { #1 }
 }

\NewDocumentCommand{\filter}{mmm}
 {
  \jason_strict_test:n { #1 }
  \bool_if:NTF \l_jason_strict_bool { #2 } { #3 }
 }
\ExplSyntaxOff

\setactivelist{yellow, blue, red, green}

\begin{document}

Match: \filter{yellow, blue, red, green}{The elements match}{The elements don't match}

Match: \filter{green, yellow, blue, red}{The elements match}{The elements don't match}

Not match: \filter{yellow, blue, red}{The elements match}{The elements don't match}

Not match: \filter{yellow, blue, red, green, purple}{The elements match}{The elements don't match}

\end{document}

在此处输入图片描述

答案2

如果您只想以不扩展的方式比较两个字符串,则可以使用将\ifx两个参数存储在具有完全扩展的替换文本的临时宏中的原语:

\documentclass{article}

\newcommand{\activetags}{yellow, blue, red, green}

\makeatletter
\newcommand\filter[1]{%
    \edef\tempA@{#1}%
    \edef\tempB@{\activetags}%
    \ifx\tempA@\tempB@
        The elements match\par
    \else
        The elements don't match\par
    \fi
}
\makeatother

\begin{document}

\filter{yellow, blue, red, green}% This should show "The elements match!"
\filter{yellow, blue, red}% This should show "The elements don't match"
\filter{yellow, blue, red, green, purple}% This should show "The elements don't match"

\end{document}

正如您所说,您的版本由于扩展问题而无法工作。如果您想以可扩展的方式执行此操作,则让第一个和第二个参数完全展开会有些棘手。

相关内容