如何迭代通过数据工具接口传递的逗号分隔列表

如何迭代通过数据工具接口传递的逗号分隔列表

我正在尝试迭代一个逗号分隔的列表,该列表本身位于文件中的一个单元格内.csv,我正在读取并迭代它datatool

按照,如何处理通过命令传递的逗号分隔列表,我以为问题可能是扩展问题。但即使将循环放在\foreach宏中调用\PROCESS然后使用\expandafter似乎也无法解决问题。

以下是 MWE:

\begin{filecontents*}{verbs.csv}
Verb,Type
touch,EA
chase,EA
hear,ENA
see,ENA
\end{filecontents*}

\begin{filecontents*}{studies.csv}
Study,TestedAs,Verbs
fox1998,actional,"touch, chase"
fox1998,nonactional,"hear, see"
\end{filecontents*}

\documentclass{article}

\usepackage{booktabs}

\usepackage{xcolor}
\definecolor{darkred}{HTML}{B22613}

\newcommand*{\EA}[1]{\textcolor{darkred}{#1}}
\newcommand*{\ENA}[1]{\textcolor{cyan}{#1}}

\usepackage{pgffor}

\usepackage{datatool}
\DTLloaddb{studies}{studies.csv}
\DTLloaddb{verbs}{verbs.csv}

\newcommand*{\EAList}{}
\DTLforeach*[\DTLiseq{\Type}{EA}]{verbs}{\Verb=Verb,\Type=Type}{%
  \expandafter\DTLifinlist\expandafter{\Verb}{\EAList}%
  {}% do nothing if already in list
  {% else add to list
    \ifdefempty{\EAList}%
    {\let\EAList\Verb}% first element of list
    {% else append to list
      \eappto\EAList{,\Verb}%
    }%
  }%
}%

\newcommand*{\ENAList}{}
\DTLforeach*[\DTLiseq{\Type}{ENA}]{verbs}{\Verb=Verb,\Type=Type}{%
  \expandafter\DTLifinlist\expandafter{\Verb}{\ENAList}%
  {}% do nothing if already in list
  {% else add to list
    \ifdefempty{\ENAList}%
    {\let\ENAList\Verb}% first element of list
    {% else append to list
      \eappto\ENAList{,\Verb}%
    }%
  }%
}%

\newcommand*{\PROCESS}[1]{%
  \foreach \x in {#1}{%
    \DTLifinlist{\x}{\EAList}%
    {% if in \EAList, print as \EA
      \EA{\x}, %
    }%
    {% else, test for others
      \DTLifinlist{\x}{\ENAList}%
      {% if in \ENAList, print as \ENA
        \ENA{\x}, %
      }%
      {% else print warning
        D'oh.
      }%
    }%
  }%
}%

\newcommand*{\PrintVerbs}[2]{%
  \DTLforeach*[\DTLiseq{\Study}{#1}\and\DTLiseq{\TestedAs}{#2}]{studies}{%
    \Study=Study,
    \TestedAs=TestedAs,
    \Verbs=Verbs%
  }{%
    \expandafter\PROCESS\expandafter{\Verbs}
  }%
}%


\begin{document}

\begin{table}[htbp]
  \begin{tabular}{ll}
    \toprule
    Study & Actional verbs tested\\
    \midrule
    Fox \& Grodzinsky (1998) & \PrintVerbs{fox1998}{actional}\\
    \ldots & \ldots\\
    \bottomrule
  \end{tabular}
\end{table}

\begin{table}[htbp]
  \begin{tabular}{ll}
    \toprule
    Study & Nonactional verbs tested\\
    \midrule
    Fox \& Grodzinsky (1998) & \PrintVerbs{fox1998}{nonactional}\\
    \ldots & \ldots\\
    \bottomrule
  \end{tabular}
\end{table}

\end{document}

得出的结果为:

在此处输入图片描述

但预期的输出是:

在此处输入图片描述

我将解释发生了什么,这样您就不必仅通过阅读代码来解读。有一个.csv名为的文件verbs.csv,其中包含列表中不同动词的一些动词类型分类。

已经有一些实验测试了这些动词,但以不同的方式对它们进行分类(具体来说,分为“动作”或“非动作”,而不是“EA”或“ENA”)。

因此,给出的类型分类verbs.csv是我想要使用的分类。我想根据我对每个动词的分类方式(而不是之前的分类方式)用不同的颜色打印每个动词。

因此,我首先收集 EA 类型动词列表,然后收集 ENA 类型动词列表。

然后,我想迭代不同的研究,这些研究都测试了不同的动词。根据动词是 EA 类型动词还是 ENA 类型动词,我想用不同的颜色打印它。

如果上述代码有效,我仍然会遇到的一个问题是会有一个多余的逗号。因此,如果您对如何对逗号分隔列表中的最后一项进行不同的处理也有建议,我将不胜感激。:)

答案1

我可以提供一个expl3基于的解决方案。

\begin{filecontents*}{verbs.csv}
Verb,Type
touch,EA
chase,EA
hear,ENA
see,ENA
\end{filecontents*}

\begin{filecontents*}{studies.csv}
Study,TestedAs,Verbs
fox1998,actional,"touch, chase"
fox1998,nonactional,"hear, see"
\end{filecontents*}

\documentclass{article}

\usepackage{xparse}
\usepackage{booktabs}

\usepackage{xcolor}
\definecolor{darkred}{HTML}{B22613}

\newcommand*{\EA}[1]{\textcolor{darkred}{#1}}
\newcommand*{\ENA}[1]{\textcolor{cyan}{#1}}

\usepackage{pgffor}

\usepackage{datatool}
\DTLloaddb{studies}{studies.csv}
\DTLloaddb{verbs}{verbs.csv}

\ExplSyntaxOn
\seq_new:N \g_liter_ealist_seq
\seq_new:N \g_liter_enalist_seq
\seq_new:N \l_liter_temp_seq

\DTLforeach*[\DTLiseq{\Type}{EA}]{verbs}{\Verb=Verb,\Type=Type}
 {
  \seq_gput_right:Nx \g_liter_ealist_seq { \Verb }
 }
\seq_gremove_duplicates:N \g_liter_ealist_seq

\DTLforeach*[\DTLiseq{\Type}{ENA}]{verbs}{\Verb=Verb,\Type=Type}
 {
  \seq_gput_right:Nx \g_liter_enalist_seq { \Verb }
 }
\seq_gremove_duplicates:N \g_liter_enalist_seq

\cs_new_protected:Nn \liter_process:n 
 {
  \seq_clear:N \l_liter_temp_seq
  \clist_map_inline:nn { #1 }
   {
    \seq_if_in:NnTF \g_liter_ealist_seq { ##1 }
     {
      \seq_put_right:Nn \l_liter_temp_seq { \EA{##1} }
     }
     {
      \seq_if_in:NnTF \g_liter_enalist_seq { ##1 }
       {
        \seq_put_right:Nn \l_liter_temp_seq { \ENA{##1} }
       }
       {
        \seq_put_right:Nn \l_liter_temp_seq { D'oh }
       }
     }
   }
   \seq_use:Nn \l_liter_temp_seq { ,~ }
 }
\cs_generate_variant:Nn \liter_process:n { V }

\NewDocumentCommand{\PrintVerbs}{mm}
 {
  \DTLforeach*[\DTLiseq{\Study}{#1}\and\DTLiseq{\TestedAs}{#2}]{studies}
   {
    \Study=Study,
    \TestedAs=TestedAs,
    \Verbs=Verbs
   }
   {
    \liter_process:V \Verbs
   }
 }
\ExplSyntaxOff


\begin{document}

\begin{table}[htbp]
  \begin{tabular}{ll}
    \toprule
    Study & Actional verbs tested\\
    \midrule
    Fox \& Grodzinsky (1998) & \PrintVerbs{fox1998}{actional}\\
    \ldots & \ldots\\
    \bottomrule
  \end{tabular}
\end{table}

\begin{table}[htbp]
  \begin{tabular}{ll}
    \toprule
    Study & Nonactional verbs tested\\
    \midrule
    Fox \& Grodzinsky (1998) & \PrintVerbs{fox1998}{nonactional}\\
    \ldots & \ldots\\
    \bottomrule
  \end{tabular}
\end{table}

\end{document}

EA 和 ENA 列表按顺序存储,并删除重复项以提高效率。然后您的\PROCESS宏将按照您的要求构建一个最终“使用”的序列,并使用逗号空格作为项目之间的分隔符。

在此处输入图片描述

相关内容