7

Is there a package that provides a command for testing whether a string is in a list? I saw several answers that define their own commands to perform this or similar tasks, but I prefer a "self-evolving", and well-documented solution for this kind of tasks. More precisely, the command should be something like this

\IfStringInList{string}{list}{DoThisIfTrue}{DoThisIfFalse}

For instance

\IfStringInList{Paul}{George,John,Paul,Ringo}{Beat it}{Roll it}

EDIT: I'm not against defining commands. I expected thas this natural functionality was present in a ready-to-use package, that can be accessed in a very simple way.

5
  • Is "list" always going to be defined as a comma-separated collection of strings?
    – Mico
    Aug 11, 2015 at 16:20
  • Probably. I think it is somehow natural, while {}{}{}..., for instance, is not.
    – ASdeL
    Aug 11, 2015 at 16:29
  • 1
    you don't need a package \in@ and \ifin@ are predefined in the latex format. Aug 11, 2015 at 16:36
  • @David: Thanks. This is interesting. Should I use makeatletter/makeatother?. I would like a plain simple command.
    – ASdeL
    Aug 11, 2015 at 16:49
  • @ASdeL you need something to access commands with @ but see Heiko's answer which is the same as mine (which I have now deleted) but just packaged for actual use. Aug 11, 2015 at 16:54

5 Answers 5

6

The xtring package provides such command:

\documentclass{article}
\usepackage{xstring}
\newcommand\IfStringInList[2]{\IfSubStr{,#2,}{,#1,}}
\begin{document}
\IfStringInList{Paul}{George,John,Paul,Ringo}{True}{False}

\IfStringInList{Joe}{George,John,Paul,Ringo}{True}{False}

\IfStringInList{ul,Ri}{George,John,Paul,Ringo}{True}{False}
\end{document}
3
  • 4
    I'm not convinced with this. I do not like that \IfSubStr{George,John,Paul,Ringo}{ul,Ri}{True}{False} is True.
    – ASdeL
    Aug 11, 2015 at 16:17
  • 2
    Good recovery. +1 Aug 11, 2015 at 18:46
  • This solution works correctly even when the first argument is empty ({}) or a macro ({\somemacro}). +1! Jun 28 at 19:08
11

Simple LaTeX with the kernel command \in@:

\documentclass{article}

\makeatletter
\newcommand*{\IfStringInList}[2]{%
  \in@{,#1,}{,#2,}%
  \ifin@
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi
}
\makeatother

\begin{document}
\IfStringInList{Paul}{George,John,Paul,Ringo}{Beat it}{Roll it}
\end{document}

Manual solution without defining a command and without \makeatletter

As requested by the comment. I do not see a sense, not to define a macro.

\csname in@\endcsname{,Paul,}{,George,John,Paul,Ringo,}%
\expandafter\ifx\csname ifin@\expandafter\endcsname\csname iftrue\endcsname
  Beat it%
\else
  Roll it%
\fi

}

The lengthy replacement for \ifin@ is needed, when this construct is inside another \if branch.

4
  • Odd I didn't see this but system says you posted a minute ahead of me, I'll delete mine:-) Aug 11, 2015 at 16:52
  • @Heiko: Nice answer, but you are still defining your own command. Off course, the command can be removed, but then makeat... must be used between begin/end{document}.
    – ASdeL
    Aug 11, 2015 at 17:13
  • 1
    @ASdeL what's to say against defining a command? (If you insist you can put the code in a package of your own and – voila – you have a package which provides the command that you want…)
    – cgnieder
    Aug 11, 2015 at 17:20
  • @clemens: See my edit in the question. Thanks.
    – ASdeL
    Aug 11, 2015 at 21:35
4

expl3 has this ready for use: \clist_if_in:nnTF {<clist>} {<item>} {<true>} {<false>}:

\documentclass{article}
\usepackage{expl3,xparse}
\ExplSyntaxOn
\NewDocumentCommand \IfStringInList {mmmm}
  { \clist_if_in:nnTF {#2} {#1} {#3} {#4} }
\ExplSyntaxOff
\begin{document}
\IfStringInList{Paul}{George,John,Paul,Ringo}{Beat it}{Roll it}% Beat it

\IfStringInList{ul,Ri}{George,John,Paul,Ringo}{Beat it}{Roll it}% Roll it
\end{document}
2

Here's a LuaLaTeX-based solution. It sets up a macro called \IfStringInList and implements it via a call to the Lua function string.find to set up "true" and "false" branches. Observe that both the target string and the search string can be quite general; in particular, the target string need not be a comma-separated collection of strings.

% !TEX TS-program = lualatex
\documentclass{article}
\usepackage{luacode} % for "\luastring" macro
\newcommand\IfStringInList[4]{%
    \directlua{if string.find(\luastring{#2},\luastring{#1}) then
                  tex.print(\luastring{#3})
               else 
                  tex.print(\luastring{#4})
               end}%
    }
\begin{document}
\IfStringInList{Paul}{George,John,Paul,Ringo}{Beat it}{Roll it}% "Beat it"

\IfStringInList{Mozart}{GeorgeJohnPaulRingo}{Strum It}{Hum it} % "Hum it"

\IfStringInList{George,John,Paul,Ringo}{ul,Ri}{True}{False}    % "False"
\end{document} 
1
  • Thank you, but I am looking for an already defined command \IfStringInList (or any other name) in a common package.
    – ASdeL
    Aug 11, 2015 at 16:34
1

Another way... EDITED to allow blank fields (A,,B)

\documentclass{article}
\usepackage{ifthen}
\newcommand\IfStringInList[4]{\stringsearch#1:#2,\relax\relax%
  \if T\found#3\else#4\fi}
\def\stringsearch#1:#2,#3\relax{\ifthenelse{\equal{#1}{#2}}{\def\found{T}}{%
  \if\relax#3\relax\def\found{F}\else\stringsearch #1:#3\relax\fi}}
\begin{document}
\IfStringInList{Paul}{George,John,Paul,Ringo}{Beat it}{Roll it}

\IfStringInList{Paul}{George,,John,Paul,Ringo}{Beat it}{Roll it}

\IfStringInList{Yanni}{George,John,Paul,Ringo}{Beat it}{Roll it}
\end{document}
1
  • Thank you, but I am looking for an already defined command \IfStringInList (or any other name) in a common package.
    – ASdeL
    Aug 11, 2015 at 16:42

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .