这个答案向我展示了如何处理任意数量的参数。我根据自己的目的对其进行了一点调整:
\usepackage{pgffor}
\newcommand*{\twolinematrix}[1]{%
\foreach \firstrowelement/\secondrowelement in {#1} {%
<something should happen here!}%
}
}
上述宏应以这样的输入为例:\autotwolinematrix{1/6, 2/7, 3/8, 4/9, 5/10}
。
我陷入了困境,因为通常情况下,如果你想创建一个矩阵(假设你已经amsmath
加载),你会这样做:
\newcommand{\manualtwolinematrix}[10]{%
\begin{matrix}
#1 & #2 & #3 & #4 & #5 \\
#6 & #7 & #8 & #9 & #10
\end{matrix}%
}
因此,这意味着您需要有逻辑来知道何时完成元素对,因为您必须放置\\
。我认为如果我们以编程方式生成矩阵,最好这样想:
\newcommand{\manualtwolinematrix}[10]{%
\begin{matrix}
#1 & #2 & #3 & #4 & #5 \\ #6 & #7 & #8 & #9 & #10
\end{matrix}%
}
其中#1 & #2 & #3 & #4 & #5 \\ #6 & #7 & #8 & #9 & #10
是宏主体中必须自动生成的字符串。我们的宏成对地获取输入,因此我们必须根据成对的输入生成此字符串。好的,那么在宏主体中,我们应该有两个变量:\firstrow
和\secondrow
。
给定每对元素,应该按顺序构建和,最后生成一个名为的变量,如下所示\firstrow
:\secondrow
\matrixbody
\matrixbody = \firstrow \\ \secondrow
你能帮我整理一下这些想法吗?
答案1
也许不如手工制作的递归宏有吸引力,但这里有一个实现expl3
。
我还添加了一个可选参数(默认为空)用于生成不同的矩阵类型;对于相应的类型,可选参数应该是p
、、或之中。b
B
v
V
\documentclass{article}
\usepackage{amsmath}
\usepackage{xparse}
\setcounter{MaxMatrixCols}{20} % or maybe more
\ExplSyntaxOn
\NewDocumentCommand{\twolinematrix}{O{}m}
{
\twoline_matrix:nn { #1 } { #2 }
}
\seq_new:N \l__twoline_i_seq
\seq_new:N \l__twoline_ii_seq
\cs_new_protected:Nn \twoline_matrix:nn
{
\seq_clear:N \l__twoline_i_seq
\seq_clear:N \l__twoline_ii_seq
\clist_map_function:nN { #2 } \twoline_add:n
\begin{#1matrix}
\seq_use:Nn \l__twoline_i_seq { & }
\\
\seq_use:Nn \l__twoline_ii_seq { & }
\end{#1matrix}
}
\cs_new_protected:Nn \twoline_add:n
{
\__twoline_add:w #1 \q_stop
}
\cs_new_protected:Npn \__twoline_add:w #1/#2 \q_stop
{
\seq_put_right:Nn \l__twoline_i_seq { #1 }
\seq_put_right:Nn \l__twoline_ii_seq { #2 }
}
\ExplSyntaxOff
\begin{document}
\[
\twolinematrix{1/6, 2/7, 3/8, 4/9, 5/10}
\qquad
\twolinematrix[b]{1/6, 2/7, 3/8, 4/9, 5/10, 6/11, 7/12, 8/13, 9/14, 10/15}
\]
\end{document}
这和 wipet 的代码其实没什么区别。
- 我们清除行容器(这里是序列)
- 我们将给定的输入映射为逗号分隔的列表,调用内部函数
\__twoline_add:w
在斜线处拆分每个项目并将各部分添加到序列中 - 我们使用序列,放置
&
在项目之间
没有必要对第一项和其他项做不同的事情,这由 来处理\seq_use:Nn
,它只添加之间项目。
与看似更紧凑的代码相比,其优点在于我们不需要重新发明轮子,而只需对逗号分隔列表的每个项目的操作给出适当的定义。
有关代码的更深入解释,请参阅:https://tug.org/TUGboat/tb39-1/tb121gregorio-expl3.pdf
答案2
例如,您可以使用以下代码:
\def\addto#1#2{\expandafter\def\expandafter#1\expandafter{#1#2}}
\def\autotwolinematrix#1{\def\firstrow{}\def\secondrow{}\atwolmA#1,/,}
\def\atwolmA#1/#2,{\ifx,#2,\pmatrix{\firstrow\cr\secondrow}\else
\ifx\firstrow\empty \def\firstrow{#1}\def\secondrow{#2}\else
\addto\firstrow{}\addto\secondrow{}\fi
\expandafter \atwolmA \fi
}
test:
$$
\autotwolinematrix{1/6, 2/7, 3/8, 4/9, 5/10}
$$
\bye
第一步:在循环中设置\firstrow
和,同时读取参数。第二步:在中使用这些宏。\secondrow
\pmatrix
答案3
在对齐内部,最好使用可扩展循环结构,因此使用expl3
或这里我直接对其进行编码。
\documentclass{article}
\makeatletter
\def\autotwolinematrix#1{%
\begin{bmatrix}%
\firstrow,#1,\relax/%
\secondrow,#1,\relax/%
}
\def\firstrow#1,#2/{\ifx\relax#2\\\else\ifx\relax#1\relax\else&\fi#2\expandafter\firstrow\fi}
\def\secondrow#1,#2/{\ifx\relax#2#1\end{bmatrix}\else#1\ifx\relax#1\relax\else&\fi\expandafter\secondrow\fi}
\makeatother
\usepackage{amsmath}
\begin{document}
$\autotwolinematrix{1/6, 2/7, 3/8, 4/9, 5/10}$
\end{document}