# 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? Oct 22 '12 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}. Oct 22 '12 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? Oct 22 '12 at 22:10
• You have to expand \String once before passing it to \IfRefList. Oct 22 '12 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. Oct 23 '12 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? Oct 22 '12 at 13:43
• @Andrew You probably have an outdated version of LaTeX3 Oct 22 '12 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. Oct 22 '12 at 14:02