两个列表的笛卡尔积作为命令的参数

两个列表的笛卡尔积作为命令的参数

朋友们,当我必须迭代列表元素时,我曾经非常痛苦,但多亏了 egreg 的建议,我已经成功地使用该etoolbox包完成了这项任务,例如:

\DeclareListParser*{\dothedance}{;}
\dothedance{\fbox}{item1; item2; item3}

现在,我尝试获取两个列表的笛卡尔积的所有对(请原谅以下 Haskell 代码):

Prelude> [ (x,y) | x <- ['A','B','C'], y <- ['a','b','c','d'] ]
[('A','a'),('A','b'),('A','c'),('A','d'),('B','a'),('B','b'),('B','c'),('B','d'),('C','a'),('C','b'),('C','c'),('C','d')]

然后,对于每一对,我想将其分成两个参数(X)并将它们传递给命令。

例如,考虑两个列表[Hello, Howdy][Ann, Mary, Kate]以下虚拟命令:

\newcommand\saysomething[2]{#1~#2}

我希望每对都是该命令的参数。因此输出将是:

Hello Ann
Hello Mary
Hello Kate
Howdy Ann
Howdy Mary
Howdy Kate

我很确定etoolbox可以帮我解决这个问题,但我尝试遍历两个列表的所有尝试都失败了。我可能忽略了一些显而易见的东西,但我需要启发。有什么想法吗?

答案1

这可能更优雅......

\documentclass{article}
\usepackage{etoolbox}

\DeclareListParser*{\dothedance}{,}

\newcommand{\saysomething}[2]{#1~#2\par}
\newcommand{\sayitto}[1]{%
  \dothedance{\saysomething{#1}}{Ann, Mary, Kate}
}


\begin{document}
\dothedance{%
\sayitto
}{Hello, Howdy}
\end{document}

生成:

Hello Ann
Hello Mary
Hello Kate
Howdy Ann
Howdy Mary
Howdy Kate

(回应评论)为了使得可以在调用时指定两个列表:

\documentclass{article}
\usepackage{etoolbox}

\DeclareListParser*{\dothedance}{,}
\DeclareListParser*{\dotheotherdance}{,}

\newcommand{\saysomething}[2]{#1~#2\par}
\newcommand{\sayitto}[1]{%
  \dothedance{\saysomething{#1}}
}

\newcommand{\dothetwostep}[3]{%
  \def\partner##1{%
    \dothedance{#1{##1}}{#3}%
  }
  \dothedance{\partner}{#2}
}


\begin{document}
\dothetwostep{\saysomething}{Hello, Howdy}{Ann, Mary, Kate}
\end{document}

答案2

为什么不 :

\documentclass{article}
\usepackage{pgffor}

\newcommand{\saysomething}[2]{ 
  \foreach \w in #1{%
  \foreach \n in #2{%
     \w~\n \par}}}  

\begin{document}
\def\Lone{ Hello, Howdy}
\def\Ltwo{ Ann, Mary, Kate}
\saysomething{\Lone}{\Ltwo}

\end{document} 

答案3

这是另一种etoolbox遵循 Paulo Cereda 的起源思想(直接嵌套循环)的解决方案。

我添加了一个\directprodM以允许 csv 列表作为宏名称。

\documentclass{article}
\usepackage{etoolbox}

% #1 is a function
% #2 and #3 are literal csv lists
\newcommand\directprod[3]{%
  \renewcommand\do[1]{%
    \begingroup
    \renewcommand\do[1]{%
      #1{##1}{####1}}% awful, indeed
    \docsvlist{#3}%
    \endgroup}%
  \docsvlist{#2}}

% #2 and #3 are macros
\newcommand\directprodM[3]{%
  \edef\next{\noexpand\directprod\noexpand#1{#2}{#3}}%
  \next}

\begin{document}

\newcommand\saysomething[2]{#1~#2\par}

\directprod\saysomething{Hello, Howdy}{Ann, Mary, Kate}

or using macros for lists:
\newcommand\listA{Hello, Howdy}
\newcommand\listB{Ann, Mary, Kate}
\directprodM\saysomething\listA\listB

\end{document}

相关内容