4

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.

  • Is "list" always going to be defined as a comma-separated collection of strings? – Mico Aug 11 '15 at 16:20
  • Probably. I think it is somehow natural, while {}{}{}..., for instance, is not. – ASdeL Aug 11 '15 at 16:29
  • 1
    you don't need a package \in@ and \ifin@ are predefined in the latex format. – David Carlisle Aug 11 '15 at 16:36
  • @David: Thanks. This is interesting. Should I use makeatletter/makeatother?. I would like a plain simple command. – ASdeL Aug 11 '15 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. – David Carlisle Aug 11 '15 at 16:54
4

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}
  • 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 '15 at 16:17
  • 2
    Good recovery. +1 – Steven B. Segletes Aug 11 '15 at 18:46
7

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.

  • Odd I didn't see this but system says you posted a minute ahead of me, I'll delete mine:-) – David Carlisle Aug 11 '15 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 '15 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…) – clemens Aug 11 '15 at 17:20
  • @clemens: See my edit in the question. Thanks. – ASdeL Aug 11 '15 at 21:35
3

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

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} 
  • Thank you, but I am looking for an already defined command \IfStringInList (or any other name) in a common package. – ASdeL Aug 11 '15 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}
  • Thank you, but I am looking for an already defined command \IfStringInList (or any other name) in a common package. – ASdeL Aug 11 '15 at 16:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.