如何测试给定的参考是否属于标签列表?

如何测试给定的参考是否属于标签列表?

这个问题是我上一个问题的延伸如何从列表中选择使用 \ref 中的结果?。我得到了非常好的、有趣的答案。不幸的是,我无法将它们应用于我的最终任务。

让我们考虑几个对象,比如方程,它们被标记为\label

\begin{equation}
2+2=4 \label{aaa}
\end{equation}

\begin{equation}
3+3=6 \label{bbb}
\end{equation}

...............

\begin{equation}
22+22=44 \label{zzz}
\end{equation}

将命令\theequation重新定义为

\renewcommand{\theequation}{eq.~\arabic{equation}}

在这种情况下,\ref{aaa}给出 eq.~1,\ref{bbb}给出 eq.~2 等等。我需要\IfRefList检查给定引用是否包含在某个引用列表中的命令。换句话说,它应该像

\IfRefList{eq.~1}{aaa;bbb;ccc} --> true
\IfRefList{eq.~4}{aaa;bbb;ccc} --> false
\IfRefList{eq.~2}{aaa;ccc} --> false
\IfRefList{eq.~1}{bbb;aaa;ccc} --> true

我将在 中使用结果\ifthenelse。列表可以包含任意数量的项目,包括 1。我已经使用上述问题中 Heiko Oberdiek 提出的解决方案检查了几种可能性。我的尝试没有奏效。非常感谢您的帮助。

答案1

引用被写入.aux文件并重新读取。命令可以部分扩展,例如~变成。因此,在前面添加\nobreakspace{}的重新定义可以防止扩展。\theequation\protect~

以下示例使用逗号分隔列表的解析器:

\documentclass{article}

\renewcommand*{\theequation}{eq.\protect~\arabic{equation}}

\usepackage{kvsetkeys}[2011/03/03]
\usepackage{refcount}[2010/12/01]

\makeatletter
\newif\if@IfRefList
\newcommand*{\IfRefList}[2]{%
  \@IfRefListfalse
  \def\IfRefList@key{#1}%
  % \comma@parse{#2}\IfRefList@test
  \begingroup
    \csname @safe@activestrue\endcsname % babel shorthands
  \edef\x{\endgroup
    \noexpand\comma@parse{#2}\noexpand\IfRefList@test
  }\x
  \if@IfRefList
    true%
  \else
    false%
  \fi
}
\newcommand*{\IfRefList@test}[1]{%
  \IfRefUndefinedBabel{#1}{%
  }{%
    \expandafter\expandafter\expandafter\def
    \expandafter\expandafter\expandafter\IfRefList@entry
    \expandafter\expandafter\expandafter{%
      \getrefbykeydefault{#1}{}{}%
    }%
    \ifx\IfRefList@key\IfRefList@entry
      \@IfRefListtrue
      \comma@break
    \fi
  }%
}%
\makeatother

\begin{document}
  \begin{equation}
    2+2=4 \label{aaa}
  \end{equation}

  \begin{equation}
    3+3=6 \label{bbb}
  \end{equation}

  \begin{equation}
    22+22=44 \label{zzz}
  \end{equation}

  \begin{center}
    \newcommand*{\test}[1]{%
      \texttt{\detokenize\expandafter{\string#1}} & #1\\%
    }
    \begin{tabular}{l@{ $\rightarrow$ }l}
      \test{\IfRefList{eq.~1}{aaa,bbb,ccc}}
      \test{\IfRefList{eq.~4}{aaa,bbb,ccc}}
      \test{\IfRefList{eq.~2}{aaa,ccc}}
      \test{\IfRefList{eq.~1}{bbb,aaa,ccc}}
    \end{tabular}
  \end{center}
\end{document}

结果

下面是一个使用分号分隔列表的解析器的示例:

\documentclass{article}

\renewcommand*{\theequation}{eq.\protect~\arabic{equation}}

\usepackage{refcount}[2010/12/01]
\usepackage{etoolbox}

\DeclareListParser*{\SemicolonForeachParser}{;}

\newif\ifIfRefList
\newcommand*{\IfRefList}[2]{%
  \IfRefListfalse
  \def\IfRefListKey{#1}%
  % \SemicolonForeachParser\IfRefListTest{#2}%
  % Expansion of #2
  \begingroup
    \csname @safe@activestrue\endcsname
    \edef\x{\endgroup
    \noexpand\SemicolonForeachParser\noexpand\IfRefListTest{#2}%
  }\x
  \ifIfRefList
    true%
  \else
    false%
  \fi
}
\newcommand*{\IfRefListTest}[1]{%
  \IfRefUndefinedBabel{#1}{%
  }{%
    \expandafter\expandafter\expandafter\def
    \expandafter\expandafter\expandafter\IfRefListEntry
    \expandafter\expandafter\expandafter{%
      \getrefbykeydefault{#1}{}{}%
    }%
    \ifx\IfRefListKey\IfRefListEntry
      \IfRefListtrue
    \fi
  }%
}%

\begin{document}
  \begin{equation}
    2+2=4 \label{aaa}
  \end{equation}

  \begin{equation}
    3+3=6 \label{bbb}
  \end{equation}

  \begin{equation}
    22+22=44 \label{zzz}
  \end{equation}

  \begin{center}
    \newcommand*{\test}[1]{%
      \texttt{\detokenize\expandafter{\string#1}} & #1\\%
    }
    \begin{tabular}{l@{ $\rightarrow$ }l}
      \test{\IfRefList{eq.~1}{aaa;bbb;ccc}} 
      \test{\IfRefList{eq.~4}{aaa;bbb;ccc}}
      \test{\IfRefList{eq.~2}{aaa;ccc}}   
      \test{\IfRefList{eq.~1}{bbb;aaa;ccc}}
    \end{tabular}
  \end{center}
\end{document}

结果

更新:针对列表以宏形式给出的情况添加了列表的扩展。

答案2

xparse基于 (LaTeX3) 的解决方案:

\documentclass{article}
\usepackage{refcount,xparse}

\renewcommand{\theequation}{eq.~\arabic{equation}}

\ExplSyntaxOn
\NewDocumentCommand{\IfRefList}{ m m m m}
 {
  \andrew_ifreflist:nnnn { #1 } { #2 } { #3 } { #4 }
 }

\cs_set_eq:NN \__andrew_getrefnumber:n \getrefnumber
\cs_set_eq:Nc \__andrew_protected_edef:w { protected@edef }

\tl_new:N \l__andrew_temp_a_tl
\tl_new:N \l__andrew_temp_b_tl
\bool_new:N \l__andrew_hit_bool
\seq_new:N \l__andrew_labellist_seq

\cs_new_protected:Npn \andrew_ifreflist:nnnn #1 #2 #3 #4
 {
  \bool_set_false:N \l__andrew_hit_bool
  \seq_set_split:Nnn \l__andrew_labellist_seq { ; } { #2 }
  \seq_map_inline:Nn \l__andrew_labellist_seq
   {
    \__andrew_compare_label_ref:nn { #1 } { ##1 }
    \bool_if:NT \l__andrew_hit_bool { \seq_map_break: }
   }
  \bool_if:NTF \l__andrew_hit_bool { #3 } { #4 }
 }
\cs_new_protected:Npn \__andrew_compare_label_ref:nn #1 #2
 {
  \__andrew_protected_edef:w \l__andrew_temp_a_tl { #1 }
  \__andrew_protected_edef:w \l__andrew_temp_b_tl { \__andrew_getrefnumber:n { #2 } }
  \tl_if_eq:NNT \l__andrew_temp_a_tl \l__andrew_temp_b_tl
   {
    \bool_set_true:N \l__andrew_hit_bool
   }
 }
\ExplSyntaxOff

\begin{document}
\begin{equation}
2+2=4 \label{aaa}
\end{equation}

\begin{equation}
3+3=6 \label{bbb}
\end{equation}

\begin{equation}
22+22=44 \label{zzz}
\end{equation}

\IfRefList{eq.~1}{aaa;bbb;ccc}{HIT}{NO HIT}

\IfRefList{eq.~2}{aaa;ccc}{HIT}{NO HIT}

\end{document}

在此处输入图片描述

相关内容