将文件列表传递给 \foreach

将文件列表传递给 \foreach

我正在尝试从配置文件中读取可变长度的列表,以便对 if 执行某些操作。

列表存储在文件中如下

list_1:x1, x2, x3
list_2:y1, y2

如果我读了数据工具包,我可以打印它们

\usepackage{datatool}
\DTLsetseparator{:}
\DTLloaddb[noheader, keys={key,value}]{config}{path_to_config_file}
\newcommand{\firstlist}{\DTLfetch{config}{key}{list_1}{value}}
\newcommand{\secondlist}{\DTLfetch{config}{key}{list_2}{value}}
...
\firstlist


\secondlist

这将打印以下输出

x1、x2、x3

y1,y2

然后我尝试将它们传递给\foreach来自前列腺素包裹

\usepackage{pgffor}
\foreach \x in { \firstlist}{%
    \foreach \y in {\secondlist}{%
        Value: \x \y
    }
}

我得到以下输出:

值:x1、x2、x3 y1、y2

我究竟做错了什么?

提前致谢!

答案1

您可以使用\DTLassignfirstmatch,它可以定义扩展到值的宏。还要注意它应该是\foreach \x \in \firstlist(没有括号)。

\begin{filecontents*}{\jobname.dat}
list_1:x1, x2, x3
list_2:y1, y2
\end{filecontents*}

\documentclass{article}
\usepackage{pgffor}
\usepackage{datatool}

\DTLsetseparator{:}
\DTLloaddb[noheader, keys={key,value}]{config}{\jobname.dat}
\DTLassignfirstmatch{config}{key}{list_1}{\firstlist=value}
\DTLassignfirstmatch{config}{key}{list_2}{\secondlist=value}

\begin{document}

\foreach \x in \firstlist {%
    \foreach \y in \secondlist {%
        Value: \x \y \par
    }
}

\end{document}

在此处输入图片描述

通常警告:我使用它filecontents*只是为了让示例自成一体。

你的\firstlist宏本质上是一组(复杂的)指令打印 x1, x2, x3并且不能在的上下文中使用\foreach,因为它需要直接扩展为列表的宏。

答案2

这用于readarray输入配置文件并listofitems对其进行解析。已编辑以在配置文件中提供标题行,并且不预先假定列表名称中的命名约定。为此,我将配置文件读取为“原始”记录数组,丢弃第一行并编写“熟”配置,其中每个记录现在都以单词开头LISTNAME。这设置为使用listofitems执行 3 层解析以\cookedconfig分离LISTNAME记录,然后:将列表名称与列表数据分离,最后,分离列表数据的组件。

从那里开始,循环使用两者\foreach\foreachitem自行编写。

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{readarray,filecontents,pgffor,lmodern}
\begin{filecontents*}{config}
This is a header row
list A:x1, x2, x3
lstB  :y1, y2
\end{filecontents*}
\begin{document}
\readrecordarray{config}\rawconfig
\def\cookedconfig{}
\makeatletter
\foreach\row in{2,...,\numexpr\rawconfigROWS-1}{%
  \g@addto@macro\cookedconfig{LISTNAME}%
  \arraytomacro\rawconfig[\row]\thisrow%
  \expandafter\g@addto@macro\expandafter\cookedconfig\expandafter{\thisrow}%
}
\makeatother
\ignoreemptyitems
\setsepchar{LISTNAME/:/,}
\readlist*\myconfig{\cookedconfig}

The list names are:\par
 \foreach\row in {1,...,\listlen\myconfig[]}{%
 \texttt{\myconfig[\row,1]}, consisting of 
 \foreachitem\x\in\myconfig[\row,2]{%
   \ifnum\xcnt=1\else, \fi\texttt{\x}}
 \par
}

The desired loop of the OP is 

\foreachitem\x\in\myconfig[1,2]{%
  \foreachitem\y\in\myconfig[2,2]{%
    Value \texttt{\x{} \y}\par
}}%
\end{document}

在此处输入图片描述

\readdef甚至可以使用在每个记录之间插入字符的“技巧” LISTNAME,从而节省一点代码:

\documentclass{article}
\usepackage{readarray,filecontents,pgffor,lmodern}
\begin{filecontents*}{config}
This is a header row
list A:x1, x2, x3
lstB  :y1, y2
\end{filecontents*}
\newcommand\cookconfig[1]{\expandafter\cookconfigaux#1\endcookconfig}
\def\cookconfigaux#1LISTNAME#2\endcookconfig{\gdef\cookedconfig{LISTNAME#2}}
\begin{document}
\readarraysepchar{LISTNAME}
\readdef{config}\rawconfig
\cookconfig{\rawconfig}
\setsepchar{LISTNAME/:/,}
\ignoreemptyitems
\readlist*\myconfig{\cookedconfig}

The list names are:\par
 \foreach\row in {1,...,\listlen\myconfig[]}{%
 \texttt{\myconfig[\row,1]}, consisting of 
 \foreachitem\x\in\myconfig[\row,2]{%
   \ifnum\xcnt=1\else, \fi\texttt{\x}}
 \par
}
The desired loop of the OP is 

\foreachitem\x\in\myconfig[1,2]{%
  \foreachitem\y\in\myconfig[2,2]{%
    Value \texttt{\x{} \y}\par
}}%
\end{document}

相关内容