![\in@ 的语法并使用宏作为参数](https://linux22.com/image/346239/%5Cin%40%20%E7%9A%84%E8%AF%AD%E6%B3%95%E5%B9%B6%E4%BD%BF%E7%94%A8%E5%AE%8F%E4%BD%9C%E4%B8%BA%E5%8F%82%E6%95%B0.png)
我尝试让命令在文档的开头接受逗号分隔的列表,然后稍后测试给定的逗号分隔列表以查看它是否包含(完全相同)的元素。因此;
\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}
正如您所说,您的版本由于扩展问题而无法工作。如果您想以可扩展的方式执行此操作,则让第一个和第二个参数完全展开会有些棘手。