我在\@for
循环方面遇到了麻烦。我有一个宏,它接受逗号分隔的列表并将每个元素放入数组的一行中。当我使用循环执行此操作时\@for
,我得到了一个我无法理解的额外行。我可以用负空格手动将其删除(如下面的注释行所示),但这不是正确的方法,所以我一定是做错了什么。这是一个最小的例子。为了进行比较,如果我手动构建我期望的循环结果,则不会出现额外的行。
\documentclass{article}
\usepackage{amsmath}
\makeatletter
\newcommand{\fbun}[1]
{\ensuremath{\left[\begin{array}{c}
\@for\xx:=#1\do {\text{\xx}\\}
% \\ [-2.75ex] % why is this required?
\end{array}\right]}}
\makeatother
\begin{document}
$\left[\begin{array}{c}
A\\
B\\
C\\
D\\
\end{array}\right]$
% same array, but generated by a macro
\fbun{A,B,C,D}
\end{document}
答案1
正如 Altermundus 所说,您不能在 的最后一行之后添加额外的{}
或其他不可见的材料。但是, 之后添加了一些额外的材料。 的实现对此不太好。\relax
tabular
\@for
\@for
由于\@for
LaTeX2e 内核有限制,我建议\forcsvlist
从etoolbox
:
\documentclass{article}
\usepackage{amsmath}
\usepackage{etoolbox}
\def\addrow#1{\text{#1}\\}
\newcommand{\fbun}[1]
{\ensuremath{\left[\begin{array}{c}
\forcsvlist\addrow{#1}%
\end{array}\right]}}
\begin{document}
$\left[\begin{array}{c}
A\\
B\\
C\\
D\\
\end{array}\right]$
\fbun{A,B,C,D}
\end{document}
答案2
在《用户指南和参考手册》第 45 页中,Leslie Lamport 写道:
&
一行中的最后一项之后必须没有,并且\\
最后一行之后也必须没有 。
$\left[\begin{array}{c}
A\\
B\\
C\\
D\\{}%
\end{array}\right]$
此代码给出一个带有空组的新行。数组的每个单元格都位于一个组中。
\@for
是所以no developable loop
你需要写类似
\fbun{A,B,C}
D
或者您可以创建一个developable loop
但它更复杂:
\makeatletter
\newcommand*{\For}[1]{\noalign{\gdef\@Do##1{#1}}\@For}
\newcommand*{\@For}[3]{%
\unless\ifnum#1 \ifnum#3>0 >\else <\fi #2
\@Do{#1}%
\expandafter\@For\expandafter{\number\numexpr#1+#3}{#2}{#3}%
\fi
}
\makeatother
$\left[\begin{array}{c}
\For{\@Alph{#1}\\}{1}{4}{1}
\end{array}\right]$
\For
例如developable loop
,您可以尝试:
\begin{tabular}{ll}
\For{A number & #1\\}{1}{20}{1}
\end{tabular}
答案3
问题是 TeX 在最后一个之后发现了一些\\
开始新行的东西(它既不是\noalign
也不\crcr
是不会)。
一种解决方案可能是使用令牌寄存器:我们在第一个单元格中开发循环,因此\xx
在 TeX 看到\\
(或&
)之后就不会出现不再定义的问题。
\usepackage{amsmath}
\makeatletter
\newcommand{\fbun}[1]{%
\begin{bmatrix}
\toks@={\@gobble}%
\@for\next:=#1\do
{\toks@=\@xp{\the\@xp\toks@\@xp\\\@xp\text\@xp{\next}}}%
\the\toks@
\end{bmatrix}}
\makeatother
我用过\@xp
(从数学)是 的简写\expandafter
;如果\text
条目周围不需要,那么
\toks@=\expandafter{\the\expandafter\toks@\next}
就足够了。初始化\toks@
为\@gobble
的效果是第一个\\
被吞噬。
我已经array
使用了bmatrix
(如果愿意,可以更改它),当然,我\ensuremath
第一步就删除了。:)
2023 年更新
我们可以利用工具让解决方案变得更简短、更易于理解expl3
。
\documentclass{article}
\usepackage{amsmath}
\ExplSyntaxOn
\NewDocumentCommand{\fbun}{O{c}m}
{
\ensuremath
{
\left[
\begin{tabular}{#1}
\clist_use:nn { #2 } { \\ }
\end{tabular}
\right]
}
}
\ExplSyntaxOff
\begin{document}
$\left[\begin{array}{c}
\text{A}\\
\text{B}\\
\text{C}\\
\text{D}\\
\end{array}\right]$
% same array, but generated by a macro
\fbun{A,B,C,D}
\fbun[l]{Aaa,Bbbbbb,Cc,Dddd}
\end{document}
答案4
\ekvcsvloop
使用提供的解决方案expkv
。我还添加了一个小的 key=value 接口expkv-cs
,支持的键是align
和formatter
(后者将获取每行的文本作为参数)。key=value 接口中还有一些快捷方式,c
is align=c
、l
is align=l
、r
is align=r
,并且每个没有 =value 的未知键都被视为格式化程序。
\documentclass{article}
\usepackage{amsmath}
\usepackage{expkv-cs}
\makeatletter
\newcommand\fbun[1][]{\fbun@kv{#1}}
% this is the output, if you don't need the bling bling of a key=value interface
% you can reduce the \fbun definition to this.
% With the current definition it'll get two arguments from \fbun@kv and as an
% additional argument reads the comma separated list.
\newcommand\fbun@out[3]
{%
\left[\begin{array}{#1}
% ekvcsvloop will result in `\\#2{<#3-element>}` for each element in the
% csv-list #3 (thanks to \expanded in a single step), `\@gobble` will
% remove the first `\\`.
\expandafter\@gobble\expanded{\ekvcsvloop{\\#2}{#3}}%
\end{array}\right]%
}
\ekvcSplitAndForward\fbun@kv\fbun@out
{
% the two keys that will correspond to an argument for \fbun@out
align = c
,formatter = \@firstofone
}
\ekvcSecondaryKeys\fbun@kv
{
% in expkv it is documented behaviour that multiple equals signs are
% allowed, the first is the one separating key from value
% `nmeta` defines the following name to be a shortcut to set whatever is
% specified in the value.
nmeta c = align=c
,nmeta l = align=l
,nmeta r = align=r
}
\ekvdefunknownNoVal{\string\fbun@kv}{\ekvcPass\fbun@kv{formatter}{#2}}
\makeatother
\begin{document}
$\fbun[\text]{Abc,B,C,D}$
$\fbun[c,\text]{Abc,B,C,D}$
$\fbun[l,\text]{Abc,B,C,D}$
$\fbun[r,\text]{Abc,B,C,D}$
$\fbun{ab,c,d}$
$\fbun[align=@{}c@{}]{ab,c,d}$
\end{document}