4

My wish is to have two different lists:

\listone{a,b,c}
\listtwo{a,c,d,e}

and to have two macros:

\iflistincludedAND{lista}{listb}{<true>}{<false>}

which returns true if every item of lista is included in listb

and

\iflistincludedOR{lista}{listb}{<true>}{<false>}

which returns true if at least of item of lista is included in listb.

Is someone clever enough and kind enough to help me to achieve it?

Many thanks!

  • 1
    Welcome to TeX.SX. Can you provide the code for this or do we have to set up all alone? ;-) It will be easier in expl3 by far. – user31729 Nov 21 '15 at 15:21
3

A little bit of playing with etoolbox's \ifinlist, \forcsvlist and booleans:

\documentclass{article}
\usepackage{etoolbox}

\newcommand*\listone{}
\newcommand*\listtwo{}
\newcommand*\listthree{}

\forcsvlist{\listadd\listone}{a,b,c}
\forcsvlist{\listadd\listtwo}{a,c,d,e}
\forcsvlist{\listadd\listthree}{d,e}

\makeatletter
% a version of \ifinlist which takes the item as last argument so we can use
% it as handler in \forcsvlist
\newcommand\my@ifinlist[4]{\ifinlist{#4}{#1}{#2}{#3}}
% a temporary boolean:
\newbool{my@tmp@bool}

\newrobustcmd\iflistincludedAND[2]{%
  \booltrue{my@tmp@bool}%
  \forlistloop{\my@ifinlist{#2}{}{\boolfalse{my@tmp@bool}}}{#1}%
  \ifbool{my@tmp@bool}%
}
\newrobustcmd\iflistincludedOR[2]{%
  \boolfalse{my@tmp@bool}%
  \forlistloop{\my@ifinlist{#2}{\booltrue{my@tmp@bool}}{}}{#1}%
  \ifbool{my@tmp@bool}%
}
\makeatother

\begin{document}

\iflistincludedOR\listone\listtwo{true}{false} % true
\iflistincludedAND\listone\listtwo{true}{false} % false

\iflistincludedOR\listthree\listtwo{true}{false} % true
\iflistincludedAND\listthree\listtwo{true}{false} % true

\iflistincludedOR\listthree\listone{true}{false} % false
\iflistincludedAND\listthree\listone{true}{false} % false

\bigskip

\iflistincludedOR\listtwo\listone{true}{false} % true
\iflistincludedAND\listtwo\listone{true}{false} % false

\iflistincludedOR\listtwo\listthree{true}{false} % true
\iflistincludedAND\listtwo\listthree{true}{false} % false

\iflistincludedOR\listone\listthree{true}{false} % false
\iflistincludedAND\listone\listthree{true}{false} % false

\end{document}
  • Thank you very much for your quick answer. It does exactly what I was looking for: problem solved! – Olivier Vogel Nov 21 '15 at 16:51
2

Not a etoolbox version, but using clist variables from expl3

\documentclass{article}

\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\NewList}{m}{%
  \clist_new:c {l_oliver_#1_clist}
  \expandafter\newcommand\csname #1\endcsname{l_oliver_#1_clist}
}

\NewDocumentCommand{\AddToList}{mm}{%
  \clist_put_right:cn {#1} {#2}
}

\bool_new:N \l_oliver_lists_equal_bool
\NewDocumentCommand{\iflistincludedAND}{mm+m+m}{
  \int_compare:nNnTF { \clist_count:c {#1} } = { \clist_count:c {#2} } {%
    \clist_map_inline:cn  {#1} { 
      \bool_set_false:N \l_oliver_lists_equal_bool
      \clist_if_in:cnTF {#2} { ##1 }{\bool_gset_true:N \l_oliver_lists_equal_bool}{ %
        \clist_map_break:N % Break the list
      }%
    }% End of inline
    \bool_if:nTF {\l_oliver_lists_equal_bool} {#3} { #4 }
  }{#4 }
}


\NewDocumentCommand{\iflistincludedOR}{mm+m+m}{%
  \bool_set_false:N \l_oliver_lists_equal_bool
  \clist_map_inline:cn  {#1} { 
    \bool_set_false:N \l_oliver_lists_equal_bool
    \clist_if_in:cnT {#2} { ##1 }{\bool_gset_true:N \l_oliver_lists_equal_bool
    }
  }% End of inline
  \bool_if:nTF {\l_oliver_lists_equal_bool} {#3} { #4 }
}

\ExplSyntaxOff

\begin{document}

\NewList{listone}
\AddToList{\listone}{a,b,c}
\NewList{listtwo}
\AddToList{\listtwo}{a,b,c,d}

\NewList{listthree}
\AddToList{\listthree}{e,f,g}


\iflistincludedAND{\listone}{\listtwo}{Yes - equal!}{Nope, not equal}

\iflistincludedOR{\listone}{\listtwo}{Yes, has one of it}{Nope, not a single one is in it}

\iflistincludedOR{\listone}{\listthree}{Yes, has one of it}{Nope, not a single one is in it}


\end{document}

enter image description here

  • Style comment: it would be better to say \NewList\listone instead of creating that csname in the code. Much clearer if you're going to use the csname directly anyway. – Sean Allred Nov 21 '15 at 16:02
2

Here's an implementation with xparse and expl3:

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\definelist}{mm}
 {
  \vogel_list_define:nn { #1 } { #2 }
 }
\NewDocumentCommand{\iflistincludedAND}{mmmm}
 {
  \vogel_list_include_and:nnnn { #1 } { #2 } { #3 } { #4 }
 }
\NewDocumentCommand{\iflistincludedOR}{mmmm}
 {
  \vogel_list_include_or:nnnn { #1 } { #2 } { #3 } { #4 }
 }

\bool_new:N \l_vogel_list_include_bool

\cs_new_protected:Nn \vogel_list_define:nn
 {
  \clist_clear_new:c { l_vogel_list_#1_clist }
  \clist_set:cn { l_vogel_list_#1_clist } { #2 }
 }

\cs_new_protected:Nn \vogel_list_include_or:nnnn
 {
  \bool_set_false:N \l_vogel_list_include_bool
  \clist_map_inline:cn  { l_vogel_list_#1_clist }
   {
    \clist_if_in:cnT { l_vogel_list_#2_clist } { ##1 }
     {
      \clist_map_break:n { \bool_set_true:N \l_vogel_list_include_bool }
     }
   }
  \bool_if:NTF \l_vogel_list_include_bool { #3 } { #4 }
 }

\cs_new_protected:Nn \vogel_list_include_and:nnnn
 {
  \bool_set_true:N \l_vogel_list_include_bool
  \clist_map_inline:cn  { l_vogel_list_#1_clist }
   {
    \clist_if_in:cnF { l_vogel_list_#2_clist } { ##1 }
     {
      \clist_map_break:n { \bool_set_false:N \l_vogel_list_include_bool }
     }
   }
  \bool_if:NTF \l_vogel_list_include_bool { #3 } { #4 }
 }

\ExplSyntaxOff

\begin{document}

\definelist{one}{a,b,c}
\definelist{two}{a,b,c,d}
\definelist{three}{a,b}
\definelist{four}{A,B}

\iflistincludedAND{one}{two}{TRUE}{FALSE}, should be TRUE

\iflistincludedAND{one}{three}{TRUE}{FALSE}, should be FALSE

\iflistincludedOR{one}{three}{TRUE}{FALSE}, should be TRUE

\iflistincludedOR{one}{four}{TRUE}{FALSE}, should be FALSE

\end{document}

enter image description here

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.