# How to test if a given reference belongs to a list of labels?

This question is a prolongation of my previous question How to choose from a list for using result in \ref?. I got really good and interesting answers. Unfortunately I can not implement them for my final task.

Let us consider few objects, say equations, which are labeled with \label,

$$2+2=4 \label{aaa}$$

$$3+3=6 \label{bbb}$$

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

$$22+22=44 \label{zzz}$$


It may also be important that the command \theequation is redefined as

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


In this case \ref{aaa} gives eq.~1, \ref{bbb} gives eq.~2 and so on. I need the command \IfRefList that check if a given reference is included in a certain reference list. In other words it should work as

\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


The result I am going to use in \ifthenelse. The list can include an arbitrary number of items including 1. I have checked several possibilities with the solution of Heiko Oberdiek proposed in the referred above question. My attempts do not work. I would be very appreciate for your help.

References are written to the .aux file and reread again. Partial expansion of commands is possible, e.g. ~ becomes \nobreakspace{}. Therefore the redefinition of \theequation adds \protect in front of ~ to prevent expansion.

The following example uses a parser for comma separated lists:

\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}
$$2+2=4 \label{aaa}$$

$$3+3=6 \label{bbb}$$

$$22+22=44 \label{zzz}$$

\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}


And an example with a parser for semicolon separated lists:

\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}
$$2+2=4 \label{aaa}$$

$$3+3=6 \label{bbb}$$

$$22+22=44 \label{zzz}$$

\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}


Update: Expansion of the list added for the case that the list is given as macro.

• Thank you. Your code, unfortunately, makes two problems for me: (1) I am using the package cleveref, the command \cref after redefinition of \theequation with \protect works incorrectly; (2) it is not clear how to use \IfRefList in \ifthenelse command: the code \ifthenelse{\IfRefList{eq.~1}{aaa,bbb,ccc}}{included}{not included} does not work (also if I replace the first argument with \equal{\IfRefList{eq.~1}{aaa,bbb,ccc}}{true}). Could you please help me? Commented Oct 22, 2012 at 13:23
• @Andrew (1) That's a problem of cleveref, make a bug report. And rethink your approach with the redefinition of \theequation. Depending on the goals, the loaded packages there might be better ways. (2) \boolean{IfRefList}. Commented Oct 22, 2012 at 17:30
• Thank you very much. With \cref the problem is already clear. If I remove ~, an incorrect result appears even for the standard \ref. Surprisingly, everything works correctly even without \protect! However, there is a new problem (Sorry!). If I define \newcommand\String{aaa,zzz} and use it as \IfRefList{eq.~1}{\String} the result is always false. Can this problem be fixed? Commented Oct 22, 2012 at 22:10
• You have to expand \String once before passing it to \IfRefList. Commented Oct 22, 2012 at 23:09
• Thanks a lot. Everything works. I still have some specific problems with the expansion. But for sure it is a different problem. Commented Oct 23, 2012 at 13:44

An xparse (LaTeX3) based solution:

\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}
$$2+2=4 \label{aaa}$$

$$3+3=6 \label{bbb}$$

$$22+22=44 \label{zzz}$$

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

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

\end{document}


• Thank you very much. I believe it should work. I only still have not fixed a problem with your codes, which use xparse. This package is installed but the codes are not compiled. Maybe something special for LaTeX3 should be done? Commented Oct 22, 2012 at 13:43
• @Andrew You probably have an outdated version of LaTeX3 Commented Oct 22, 2012 at 13:45
• Maybe you are right. I will try to update it. I am only not sure that my colleagues with whom I am preparing the LaTeX documents will be happy to do the same with their systems. Anyway, thank you very much. Your solutions are useful for me. Commented Oct 22, 2012 at 14:02