4

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,

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

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.

Andrew
  • 377

2 Answers2

4

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

Result

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

Result

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

Heiko Oberdiek
  • 271,626
  • 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? – Andrew 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}. – Heiko Oberdiek 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? – Andrew Oct 22 '12 at 22:10
  • You have to expand \String once before passing it to \IfRefList. – Heiko Oberdiek 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. – Andrew Oct 23 '12 at 13:44
3

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

enter image description here

egreg
  • 1,121,712
  • 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? – Andrew Oct 22 '12 at 13:43
  • @Andrew You probably have an outdated version of LaTeX3 – egreg 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. – Andrew Oct 22 '12 at 14:02