3

I have a large amount of data stored in a .csv file. To ensure that the input data is OK, I do a lot of tests. Among other things, I would like to test whether, a special type (typA) has the same description several times. In my case that would be a mistake!

To detect this error, I would like to store all descriptions in an array and whenever a new one is added I would iterate through the array and see whether the sting is already part of the array.

To solve this, I started based on this old question: Storing an array of strings in a command.

I especially took egreg's "Update for TUG 2024" answer here https://tex.stackexchange.com/a/215571/104358 to add the array handling. I just added the edits from the comments to store the array persistent.

Here is my MWE:

\documentclass[10pt,oneside,a4paper]{article}
\usepackage{ifthen}
\usepackage{pgfplotstable}
\pgfplotsset{compat=newest}
\setlength\parindent{0pt}

% Got it from here: https://tex.stackexchange.com/a/215571/104358 / Just small edits, see comments
\ExplSyntaxOn
\NewDocumentCommand{\storeData}{mm}
{
    \bcp_store_data:nn { #1 } { #2 }
}

\NewDocumentCommand{\appendData}{mm}
{
    \bcp_append_data:nn { #1 } { #2 }
}

\NewExpandableDocumentCommand{\getData}{O{1}m}
{
    \bcp_get_data:nn { #1 } { #2 }
}

\NewExpandableDocumentCommand{\getLength}{m}
{
    \seq_count:c { l_bcp_data_#1_seq }
}

\NewDocumentCommand{\removeLast}{om}
{
    \IfNoValueTF { #1 }
    {
        \bcp_remove_last:Nn \g_tmpa_tl { #2 }
    }
    {
        \bcp_remove_last:Nn #1 { #2 }
    }
}

\NewDocumentCommand{\processData}{O{,~}mo}
{% #1 = separator, #2 = list name, #3 = template
    \IfNoValueTF{#3}
    {% no template, just use the list with the optional separator,
        % default comma-space
        \seq_use:cn { l_bcp_data_#2_seq } { #1 }
    }
    {% template given
        \seq_map_inline:cn { l_bcp_data_#2_seq } { #3 }
    }
}

\cs_new_protected:Npn \bcp_store_data:nn #1 #2
{
    % create the sequence if it doesn't exist or clear it if it exists
    \seq_gclear_new:c { l_bcp_data_#1_seq }
    % append the items
    \__bcp_append_data:nn { #1 } { #2 }
}

\cs_new_protected:Npn \bcp_append_data:nn #1 #2
{
    % create the sequence if it doesn't exist, do nothing if it exists
    \seq_if_exist:cF { l_bcp_data_#1_seq }
    { \seq_new:c { l_bcp_data_#1_seq } }
    % append the items
    \__bcp_append_data:nn { #1 } { #2 }
}

\cs_new_protected:Npn \__bcp_append_data:nn #1 #2
{
    % append items one at a time
    \tl_map_inline:nn { #2 }
    {
        \seq_gput_right:cn { l_bcp_data_#1_seq } { ##1 }
    }
}

\cs_new:Npn \bcp_get_data:nn #1 #2
{
    % retrieve the requested item
    \seq_item:cn { l_bcp_data_#2_seq } { #1 }
}

\cs_new_protected:Nn \bcp_remove_last:Nn
{
    \seq_gpop_right:cN { l_bcp_data_#2_seq } #1
}
\ExplSyntaxOff


\begin{filecontents}{data.csv}
Type,Description
typA,description0 % Add this to the array
typB,description1
typA,description2 % Add this to the array
typA,description2 % Add this to the array => ERROR, because this description is already there!
\end{filecontents}
\pgfplotstableread[col sep=comma]{data.csv}{\csvdata}
\pgfplotstablegetrowsof{\csvdata}

\newcommand{\checkRoomDuplicates}{
    \newcount\counter
    \newcount\maxCounter
    \counter=0
    \maxCounter=\getLength{roomArray}

    \pgfplotstablegetelem{\pgfplotstablerow}{Type}\of{\csvdata}
    \ifthenelse{\equal{\pgfplotsretval}{typA}}{ % Only do something, when Typ is typA 
        \pgfplotstablegetelem{\pgfplotstablerow}{Description}\of{\csvdata}

        MaxCounter: \the\maxCounter\newline
  
        \edef\roomArrayLength{\getLength{roomArray}}
        \ifthenelse{\equal{\roomArrayLength}{0}}{
            \appendData{roomArray}{{\pgfplotsretval}}
        }{
            \loop
            \ifnum\counter<\maxCounter
            \advance\counter by 1

            Counter: \the\counter\newline
        
            RETURN VALUE:\pgfplotsretval\newline
            \edef\roomDescription{\getData[\counter]{roomArray}}
            DESCRIPTION:\roomDescription\newline % => Why is this value "description2" and NOT "description0"?

            \ifthenelse{\equal{\pgfplotsretval}{\roomDescription}}{
                DOUBLE ROOM!\newline
            }{}
            \repeat
            \appendData{roomArray}{{\pgfplotsretval}}
        }
        \processData{roomArray}\newline
        \vspace{5mm}
    }{}
}

\pgfplotstableset{
every column/.style={
        assign cell content/.code={
            \ifnum\pgfplotstablecol=0 % Do this only once per row
                \checkRoomDuplicates{}
            \fi
       },
    }
}

\begin{document}
\pgfplotstabletypeset{\csvdata}
\end{document}

Here is the output:

Output

What I don't understand is, why returns \processData{roomArray} always a repetition of the current description value and not also the old and stored ones? I think this is the reason, why my routine is not working like expected.

I would expect, that for the first time, when this routine is proceed:

\edef\roomDescription{\getData[\counter]{roomArray}}
DESCRIPTION:\roomDescription

\roomDescription is "description0" and NOT "description2" for \counter = 1

25.07.24 EDIT based on the comments

In general, the data I'm dealing with belong to my overall smartHome electric plan. All this is based on this post but much more complex now. So these data's contain Room descriptions, Component Identifier, KNX-Addresses, Fuse and Phase Information, component coordinates within my house layout and a lot of more details. So out of this, at the end I will wire my house.

All these information are given by an input.csv data. And then my LaTeX routines check and format these data. For example, the input data contain a component Identifier but in my generated table at the end, I want to see the circuit symbol. So I have implemented a routine to print the correct symbol based on the component identifier. Another example is, that I generate a hash value out of dedicated information from my input data and store them also in the table.

Additional I print a 2D graphic out of these data. That means I get a "how to wire" table and additional a TikZ image, "where to install" these components. And much more... The most of these Features are already working.

So to come back to my question, I'm trying to find a way to work with string arrays in LaTeX in an efficient and user-friendly way.

Of course, my MWE just shows a very little part of this. My original raw data have 20 columns and more than 300 rows. And I know, I could also do this with other tools, so checking the input data within python (or where ever) and then just bring the corrected data to LaTeX, but I have a running CI/CD environment which just supports LaTeX in the moment I just want to know how to do this within LaTeX :)

16
  • What needs to be done when a duplicate description is found? For the example you just print DOUBLE ROOM, is it indeed the case that you want to print a message in the document but process it normally otherwise? I'm asking because when this is not the case and you need to actually change the source data when something like this is found then it would be easier to process this data outside of LaTeX. For example in a Linux terminal sort data.csv|uniq -d would give you all duplicate lines. Commented Jul 23, 2024 at 14:58
  • The source data must be untouched (these are data‘s handled and edited by a group of persons) I just removed the part where my error handling comes into action. Right now, I just print a pdfcomment with the dedicated error reason. Commented Jul 23, 2024 at 15:50
  • @Marijn Regarding your proposal to test these within Linux, this is possible of course. But I do more than 100 tests here and it is embedded in a CI/CD system where I don't want to bring more tools into account... Another reason is, that I want to implement some other Feature where I also need string array handling, so it would be great to have a LaTeX solution :) Commented Jul 23, 2024 at 16:18
  • I am not shure at all, but try it gist.github.com/AnMnv/c6901de23722f9c55035053cfb150e9c if it helps, cool, othervise I will delete it Commented Jul 25, 2024 at 14:23
  • @WinnieNotThePooh unfortunately it doesn't work. I have still the same issue like described in my question. Commented Jul 25, 2024 at 16:35

1 Answer 1

3
+150

Probably not the best way to do whatever your actual task is, but perhaps this helps:

\documentclass[10pt,oneside,a4paper]{article}
\usepackage{ifthen}
\usepackage{pgfplotstable}
\pgfplotsset{compat=newest}
\setlength\parindent{0pt}

% Got it from here: https://tex.stackexchange.com/a/215571/104358 / Just small edits, see comments
\ExplSyntaxOn
\NewDocumentCommand{\storeData}{mm}
{
  \gcp_store_data:nn { #1 } { #2 }
}

\NewDocumentCommand{\appendData}{mm}
{
  \gcp_append_data:ne { #1 } { #2 }
}

\NewExpandableDocumentCommand{\getData}{O{1}m}
{  
  \gcp_get_data:nn { #1 } { #2 }
}

\NewExpandableDocumentCommand{\getLength}{m}
{
  \seq_count:c { g_gcp_data_#1_seq }
}

\NewDocumentCommand{\removeLast}{om}
{
  \IfNoValueTF { #1 }
  {
    \gcp_remove_last:Nn \g_tmpa_tl { #2 }
  }
  {
    \gcp_remove_last:Nn #1 { #2 }
  }
}

\NewDocumentCommand{\processData}{O{,~}mo}
{% #1 = separator, #2 = list name, #3 = template
  \IfNoValueTF{#3}
  {% no template, just use the list with the optional separator,
    % default comma-space
    \seq_use:cn { g_gcp_data_#2_seq } { #1 }
  }
  {% template given
    \seq_map_inline:cn { g_gcp_data_#2_seq } { #3 }
  }
}

\cs_new_protected:Npn \gcp_store_data:nn #1 #2
{
  % create the sequence if it doesn't exist or clear it if it exists
  \seq_gclear_new:c { g_gcp_data_#1_seq }
  % append the items
  \__gcp_append_data:nn { #1 } { #2 }
}

\cs_new_protected:Npn \gcp_append_data:nn #1 #2
{
  % create the sequence if it doesn't exist, do nothing if it exists
  \seq_if_exist:cF { g_gcp_data_#1_seq }
  { \seq_new:c { g_gcp_data_#1_seq } }
  % append the items
  \__gcp_append_data:nn { #1 } { #2 }
}
\cs_generate_variant:Nn \gcp_append_data:nn {ne}
\cs_new_protected:Npn \__gcp_append_data:nn #1 #2
{
  % append items one at a time
  \tl_map_inline:nn { #2 }
  {
    \seq_gput_right:cn { g_gcp_data_#1_seq } { ##1 }
  }
}

\cs_new:Npn \gcp_get_data:nn #1 #2
{
  % retrieve the requested item
  \seq_item:cn { g_gcp_data_#2_seq } { #1 }
}

\cs_new_protected:Nn \gcp_remove_last:Nn
{
  \seq_gpop_right:cN { g_gcp_data_#2_seq } #1
}
\NewDocumentCommand \showseq {}
{
  \seq_show:N \g_gcp_data_roomArray_seq
}

\int_new:N \l_gcp_counter_int
\int_new:N \l_gcp_maxcounter_int
\seq_new:N \g_gcp_data_roomArray_seq
\NewDocumentCommand{\checkRoomDuplicates} {}
{
  \pgfplotstablegetelem{\pgfplotstablerow}{Type}\of{\csvdata}
  \tl_if_eq:neT {typA} {\pgfplotsretval}
  {
    \pgfplotstablegetelem{\pgfplotstablerow}{Description}\of{\csvdata}
      RETURN ~ VALUE:~\pgfplotsretval \par
      \seq_if_in:NeT \g_gcp_data_roomArray_seq {\pgfplotsretval}
      {
        DOUBLE ~ ROOM!\par
      }
      \appendData{roomArray}{{\pgfplotsretval}}
    \processData{roomArray}\par
    \vspace{5mm}\par
  }
}
\ExplSyntaxOff


\begin{filecontents}{data.csv}
  Type,Description
  typA,description0 % Add this to the array
  typB,description1
  typA,description2 % Add this to the array
  typA,description2 % Add this to the array => ERROR, because this description is already there!
\end{filecontents}
\pgfplotstableread[col sep=comma]{data.csv}{\csvdata}
\pgfplotstablegetrowsof{\csvdata}

\pgfplotstableset{
  every column/.style={
    assign cell content/.code={
      \ifnum\pgfplotstablecol=0 % Do this only once per row
      \checkRoomDuplicates{}
      \fi
    },
  }
}

\begin{document}
  \pgfplotstabletypeset{\csvdata}
\end{document}

Edit

I'm not sure if this is what you want, but here's a version with a postscript. Note that the check is sensitive to spaces, so I altered the data slightly.

\documentclass[10pt,oneside,a4paper]{article}
\usepackage{ifthen}
\usepackage{pgfplotstable}
\pgfplotsset{compat=newest}
\setlength\parindent{0pt}

% Got it from here: https://tex.stackexchange.com/a/215571/104358 / Just small edits, see comments
\ExplSyntaxOn
\NewDocumentCommand{\storeData}{mm}
{
  \gcp_store_data:nn { #1 } { #2 }
}

\NewDocumentCommand{\appendData}{mm}
{
  \gcp_append_data:ne { #1 } { #2 }
}

\NewExpandableDocumentCommand{\getData}{O{1}m}
{  
  \gcp_get_data:nn { #1 } { #2 }
}

\NewExpandableDocumentCommand{\getLength}{m}
{
  \seq_count:c { g_gcp_data_#1_seq }
}

\NewDocumentCommand{\removeLast}{om}
{
  \IfNoValueTF { #1 }
  {
    \gcp_remove_last:Nn \g_tmpa_tl { #2 }
  } {
    \gcp_remove_last:Nn #1 { #2 }
  }
}

\NewDocumentCommand{\processData}{O{,~}mo}
{% #1 = separator, #2 = list name, #3 = template
  \IfNoValueTF{#3}
  {% no template, just use the list with the optional separator,
    % default comma-space
    \seq_use:cn { g_gcp_data_#2_seq } { #1 }
  } {% template given
    \seq_map_inline:cn { g_gcp_data_#2_seq } { #3 }
  }
}

\cs_new_protected:Npn \gcp_store_data:nn #1 #2
{
  % create the sequence if it doesn't exist or clear it if it exists
  \seq_gclear_new:c { g_gcp_data_#1_seq }
  % append the items
  \__gcp_append_data:nn { #1 } { #2 }
}

\cs_new_protected:Npn \gcp_append_data:nn #1 #2
{
  % create the sequence if it doesn't exist, do nothing if it exists
  \seq_if_exist:cF { g_gcp_data_#1_seq }
  { \seq_new:c { g_gcp_data_#1_seq } }
  % append the items
  \__gcp_append_data:nn { #1 } { #2 }
}
\cs_generate_variant:Nn \gcp_append_data:nn {ne}
\cs_new_protected:Npn \__gcp_append_data:nn #1 #2
{
  % append items one at a time
  \tl_map_inline:nn { #2 }
  {
    \seq_gput_right:cn { g_gcp_data_#1_seq } { ##1 }
  }
}

\cs_new:Npn \gcp_get_data:nn #1 #2
{
  % retrieve the requested item
  \seq_item:cn { g_gcp_data_#2_seq } { #1 }
}

\cs_new_protected:Nn \gcp_remove_last:Nn
{
  \seq_gpop_right:cN { g_gcp_data_#2_seq } #1
}

\int_new:N \l_gcp_counter_int
\int_new:N \l_gcp_maxcounter_int
\seq_new:N \g_gcp_data_roomArray_seq
\NewDocumentCommand{\checkRoomDuplicates} {}
{
  \pgfplotstablegetelem{\pgfplotstablerow}{Type}\of{\csvdata}
  \tl_if_eq:neT {typA} {\pgfplotsretval}
  {
    \pgfplotstablegetelem{\pgfplotstablerow}{Description}\of{\csvdata}
      RETURN ~ VALUE:~\pgfplotsretval \par
      \seq_if_in:NeT \g_gcp_data_roomArray_seq {\pgfplotsretval}
      {
        DOUBLE ~ ROOM!\par
      }
      \appendData{roomArray}{{\pgfplotsretval}}
    \processData{roomArray}\par
    \vspace{5mm}\par
  }
}
\prg_new_conditional:Npnn \gcp_array_if_in:nn #1#2 { p, T, TF, F }
{
%   \seq_show:c {g_gcp_data_#1_seq}
  \seq_if_exist:cTF {g_gcp_data_#1_seq}
  {
    \seq_if_in:cnTF {g_gcp_data_#1_seq} { #2 } { \prg_return_true: } { \prg_return_false: }
  }{ \prg_return_false: }
}
\prg_generate_conditional_variant:Nnn \gcp_array_if_in:nn { ne } {  T, TF, F }
\cs_new_eq:NN \IfInArrayTF \gcp_array_if_in:neTF
\cs_new_eq:NN \IfInArrayT \gcp_array_if_in:neT
\cs_new_eq:NN \IfInArrayF \gcp_array_if_in:neF
\ExplSyntaxOff


\begin{filecontents}[overwrite]{data.csv}
  Type,Description%
  typA,description0% Add this to the array
  typB,description1%
  typA,description2% Add this to the array
  typA,description2% Add this to the array => ERROR, because this description is already there!
\end{filecontents}
\pgfplotstableread[col sep=comma]{data.csv}{\csvdata}
\pgfplotstablegetrowsof{\csvdata}

\pgfplotstableset{
  every column/.style={
    assign cell content/.code={
      \ifnum\pgfplotstablecol=0 % Do this only once per row
      \checkRoomDuplicates{}
      \fi
    },
  }
}

\begin{document}
\pgfplotstabletypeset{\csvdata}

\IfInArrayTF{roomArray}{aardvark}{some aardvarks, yes}{no aardvarks, no} ;
\IfInArrayTF{roomArray}{description0}{indubitably}{certainly not} ;
\IfInArrayT{roomArray}{description4}{fourth} ;
\IfInArrayT{roomArray}{description2}{second} ;
\IfInArrayF{roomArray}{description33}{thirty-third} ;
\IfInArrayF{roomArray}{description0}{zero} ;

Expect: 

no aardvarks, no ; indubitably ; ; second ; thirty-third ; ;
\end{document}

Edit Again

This is a response to a request for an additional function \setData{}{}{}. Note that the underlying expl3 uses change rather than set because expl3 already uses set pervasively.

\documentclass[10pt,oneside,a4paper]{article}
\usepackage{ifthen}
\usepackage{pgfplotstable}
\pgfplotsset{compat=newest}
\setlength\parindent{0pt}

% Got it from here: https://tex.stackexchange.com/a/215571/104358 / Just small edits, see comments
\ExplSyntaxOn
\NewDocumentCommand{\storeData}{mm}
{
  \gcp_store_data:nn { #1 } { #2 }
}

\NewDocumentCommand{\appendData}{mm}
{
  \gcp_append_data:ne { #1 } { #2 }
}

\NewExpandableDocumentCommand{\getData}{O{1}m}
{
  \gcp_get_data:nn { #1 } { #2 }
}

\NewExpandableDocumentCommand{\getLength}{m}
{
  \seq_count:c { g_gcp_data_#1_seq }
}

\NewDocumentCommand \setData {mmm}
{
  \gcp_change_data:nne { #1 } { #2 } { #3 }
}

\NewDocumentCommand{\removeLast}{om}
{
  \IfNoValueTF { #1 }
  {
    \gcp_remove_last:Nn \g_tmpa_tl { #2 }
  } {
    \gcp_remove_last:Nn #1 { #2 }
  }
}

\NewDocumentCommand{\processData}{O{,~}mo}
{% #1 = separator, #2 = list name, #3 = template
  \IfNoValueTF{#3}
  {% no template, just use the list with the optional separator,
    % default comma-space
    \seq_use:cn { g_gcp_data_#2_seq } { #1 }
  } {% template given
    \seq_map_inline:cn { g_gcp_data_#2_seq } { #3 }
  }
}

\cs_new_protected:Npn \gcp_store_data:nn #1 #2
{
  % create the sequence if it doesn't exist or clear it if it exists
  \seq_gclear_new:c { g_gcp_data_#1_seq }
  % append the items
  \__gcp_append_data:nn { #1 } { #2 }
}

\cs_new_protected:Npn \gcp_append_data:nn #1 #2
{
  % create the sequence if it doesn't exist, do nothing if it exists
  \seq_if_exist:cF { g_gcp_data_#1_seq }
  { \seq_new:c { g_gcp_data_#1_seq } }
  % append the items
  \__gcp_append_data:nn { #1 } { #2 }
}
\cs_generate_variant:Nn \gcp_append_data:nn {ne}
\cs_new_protected:Npn \__gcp_append_data:nn #1 #2
{
  % append items one at a time
  \tl_map_inline:nn { #2 }
  {
    \seq_gput_right:cn { g_gcp_data_#1_seq } { ##1 }
  }
}

\cs_new:Npn \gcp_get_data:nn #1 #2
{
  % retrieve the requested item
  \seq_item:cn { g_gcp_data_#2_seq } { #1 }
}

\cs_new_protected:Nn \gcp_remove_last:Nn
{
  \seq_gpop_right:cN { g_gcp_data_#2_seq } #1
}

\int_new:N \l_gcp_counter_int
\int_new:N \l_gcp_maxcounter_int
\seq_new:N \g_gcp_data_roomArray_seq
\NewDocumentCommand{\checkRoomDuplicates} {}
{
  \pgfplotstablegetelem{\pgfplotstablerow}{Type}\of{\csvdata}
  \tl_if_eq:neT {typA} {\pgfplotsretval}
  {
    \pgfplotstablegetelem{\pgfplotstablerow}{Description}\of{\csvdata}
    RETURN ~ VALUE:~\pgfplotsretval \par
    \seq_if_in:NeT \g_gcp_data_roomArray_seq {\pgfplotsretval}
    {
      DOUBLE ~ ROOM!\par
    }
    \appendData{roomArray}{{\pgfplotsretval}}
    \processData{roomArray}\par
    \vspace{5mm}\par
  }
}
\prg_new_conditional:Npnn \gcp_array_if_in:nn #1#2 { p, T, TF, F }
{
  \seq_if_exist:cTF {g_gcp_data_#1_seq}
  {
    \seq_if_in:cnTF {g_gcp_data_#1_seq} { #2 } { \prg_return_true: } { \prg_return_false: }
  }{ \prg_return_false: }
}
\prg_generate_conditional_variant:Nnn \gcp_array_if_in:nn { ne } {  T, TF, F }
\cs_new_eq:NN \IfInArrayTF \gcp_array_if_in:neTF
\cs_new_eq:NN \IfInArrayT \gcp_array_if_in:neT
\cs_new_eq:NN \IfInArrayF \gcp_array_if_in:neF

\cs_new_protected:Nn \gcp_change_data:nnn
{ % modification of append above
  \seq_if_exist:cF { g_gcp_data_#1_seq }
  { \seq_new:c { g_gcp_data_#1_seq } }
  \__gcp_change_data:nnn { #1 } { #2 } { #3 }
}
\cs_generate_variant:Nn \gcp_change_data:nnn {nne}
\cs_new_protected:Nn \__gcp_change_data:nnn
{ % modification of append above
  % replace item
  \seq_gset_item:cnnF { g_gcp_data_#1_seq } { #2 } { #3 }
  { % if the sequence doesn't have an item at position #2
    % if you want an error instead, delete this clause and the 'F' from the line above
    NOTHING ~ TO ~ REPLACE ~ --- ~ APPENDING
    \seq_gput_right:ce { g_gcp_data_#1_seq } { #3 }
  }
}
\NewDocumentCommand \showArray { m }
{
  \seq_show:c { g_gcp_data_#1_seq }
}
\ExplSyntaxOff


\begin{filecontents}[overwrite]{data.csv}
  Type,Description%
  typA,description0% Add this to the array
  typB,description1%
  typA,description2% Add this to the array
  typA,description2% Add this to the array => ERROR, because this description is already there!
\end{filecontents}
\pgfplotstableread[col sep=comma]{data.csv}{\csvdata}
\pgfplotstablegetrowsof{\csvdata}

\pgfplotstableset{
  every column/.style={
    assign cell content/.code={
      \ifnum\pgfplotstablecol=0 % Do this only once per row
        \checkRoomDuplicates{}
      \fi
    },
  }
}

\begin{document}
\pgfplotstabletypeset{\csvdata}

\IfInArrayTF{roomArray}{aardvark}{some aardvarks, yes}{no aardvarks, no} ;
\IfInArrayTF{roomArray}{description0}{indubitably}{certainly not} ;
\IfInArrayT{roomArray}{description4}{fourth} ;
\IfInArrayT{roomArray}{description2}{second} ;
\IfInArrayF{roomArray}{description33}{thirty-third} ;
\IfInArrayF{roomArray}{description0}{zero} ;

Expect:

no aardvarks, no ; indubitably ; ; second ; thirty-third ; ;

\setData{roomArray}{3}{family room}
\setData{roomArray}{10}{executive suite}
\setData{roomArsay}{1}{sea views}

\IfInArrayTF{roomArray}{family room}{welcomes children}{adults only};
\IfInArrayTF{roomArray}{executive suite}{ooh!}{too posh for us};
\IfInArrayTF{roomArray}{sea views}{look at those waves}{not on the coast};
\IfInArrayTF{roomArsay}{sea views}{beach resort}{no sandcastles here};

Expect:

WARNING NOTHING TO REPLACE --- APPENDING
WARNING NOTHING TO REPLACE --- APPENDING

welcomes children ; ooh! ; not on the coast ; beach resort ;


\end{document}
10
  • 1
    Amazing! Yes this is what I was looking for! Accepted as this was the main scope of my question :) But can you maybe also add an additional function like isPartOfArray[2] where I have two input variables (1. any string 2. target array) and an output like true / false depending on the input string? So if this string is equal to one element in the array return 'true' otherwise false. Commented Jul 25, 2024 at 21:50
  • @PascalS But isn't that what \seq_if_in:NnTF <name of sequence> <string> {if true} {if false} already does? it doesn't make sense, imho, to have that spit out true or false and then use \ifthenelse afterwards. expl3 provides boolean processing out-of-the-box. but there isn't really an array here. (I guess a sequence is a one-dimensional one, but that's all.) or maybe that's what pgfplotstable handles? (I've never used it.) perhaps this is why egreg said earlier you're probably using the wrong tools .... Commented Jul 26, 2024 at 0:45
  • @PascalS are you just looking for a wrapper around \seq_if_in:cnTF? so you could say something like \wrappermacro {<seq identifier>}{<token list to search for>}{<true>}{<false>}? because that would make a lot more sense .... Note that nothing in this code guarantees what you are testing is a string - not unless the table handling already does that. Commented Jul 26, 2024 at 5:07
  • 1
    @PascalS Please see edit. But there's something odd about this as I'm getting an additional space. Commented Jul 26, 2024 at 15:23
  • 1
    @Pascal yes. this method wouldn't work if you needed both columns from the table, as it is only storing the second as far as I can tell. but \setData should work OK/ at least it seemed to. but if you ask a dedicated followup, you'll probably get an egreg answer :-). Commented Sep 19, 2024 at 7:53

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.