我有一个特殊问题,我想用 来解决etoolbox
,但我不知道该怎么做。我想做的是根据上一个表中的信息自动生成一个表。最好用一个例子来解释:
\newcounter{numc}
\setcounter{numc}{0}
\newcolumntype{n}{>{\thenumc.}r<{\addtocounter{numc}{1}}}
% This is simply a column displaying the row number.
\newrobustcmd{\push}[1]{\listadd{\numcount}{\thenumc} \listadd{\ncom}{#1}}
% This command may have to be defined differently, depending on the missing code below.
\begin{xtabular}{ n l l }
& row1,col2 & row1,col3 \\
& row2,col2 & row2,col3 \\ \push{Comment for row 2.}
& row3,col2 & row3,col3 \\
& row4,col2 & row4,col3 \\ \push{Comment for row 4.}
& row5,col2 & row5,col3 \\ \push{Comment for row 5.}
\end{xtabular}
\begin{xtabular}{ r l }
% The code for auto-generating the second table goes here.
% The first column is supposed to be the values in the numcount list, minus 1.
% The second column is supposed to be the text in the ncom list.
\end{xtabular}
因此输出结果应如下:
表格1:
1. row1,col2 row1,col3
2. row2,col2 row2,col3
3. row3,col2 row3,col3
4. row4,col2 row4,col3
5. row5,col2 row5,col3
表 2:
2. Comment for row 2.
4. Comment for row 4.
5. Comment for row 5.
但是,我找不到第二个表中缺失代码的好解决方案。代码应该从第一个列表生成第一列(numcount
),从第二个列表生成第二列(ncom
)。
您对于我如何解决这个问题有什么建议吗?
答案1
正如已经评论的那样,由于环境是局部范围,所以列表仅在表内定义,因此\listadd
不起作用。因此,我们需要全局版本。tabular
\listgadd
和然后你将其添加\thenumc
到列表中,但\thenumc
直到使用列表本身时才会展开,这就是我们\listxadd
在这里使用 ned 的原因(\listeadd
不是全局的)。
(这同样适用于\appto
我实际使用的宏。)
我没有使用etoolbox
' 列表,而是使用原始宏。此外,我只定义了一个宏,其中实际内容由 分隔/
,我只需要循环一现在列出。
该计数器intXI
用于检测宏\push
的第一行和最后一行\mytable
。
我还在宏\push
之前推送了该命令\\
,因为
- 没有混淆
\thenumc
(\push
宏落在n
下一行的列中) - 表格末尾没有空行。
迷你解决方案
在这个简单的例子中,我们可以使用
\ifnum\value{intXI}=1\relax%
\xappto\mytable{\thenumc & #1}%
\else%
\xappto\mytable{\noexpand\\\thenumc & #1}%
\fi%
在\push
宏中无需使用循环。
代码
\documentclass{article}
\usepackage{etoolbox}
\usepackage{array}
\usepackage{pgffor}
\newcounter{numc}\newcounter{intXI}
\newcolumntype{n}{>{\stepcounter{numc}\thenumc.}r}
\newrobustcmd{\push}[1]{%
\stepcounter{intXI}%
\ifnum\value{intXI}=1\relax%
\xappto\mylist{\thenumc/{#1}}%
\else%
\xappto\mylist{,\thenumc/{#1}}%
\fi%
}
\begin{document}
\begin{tabular}{ n l l }
& row1,col2 & row1,col3 \\
& row2,col2 & row2,col3 \push{Comment for row 2.} \\
& row3,col2 & row3,col3 \\
& row4,col2 & row4,col3 \push{Comment for row 4.} \\
& row5,col2 & row5,col3 \push{Comment for row 5.} \\
\end{tabular}
\foreach \contentn/\contentt in \mylist {%
\addtocounter{intXI}{-1}%
\ifnum0=\value{intXI}\relax
\xappto\mytable{%
\contentn & \contentt%
}%
\else
\xappto\mytable{%
\contentn & \contentt\noexpand\\%
}%
\fi%
}%
\begin{tabular}{ r l }
\mytable
\end{tabular}
\end{document}
输出
答案2
etoolbox
如果您对不使用但使用 LaTeX3 环境的替代解决方案感兴趣xparse
,请参阅这里:
\documentclass{article}
\usepackage{array,xparse}
\newcounter{numc}
\newcolumntype{n}{>{\stepcounter{numc}\thenumc.}r}
\ExplSyntaxOn
\NewDocumentEnvironment{xtabular}{ m }
{
\seq_gclear:N \g_eiterorm_pushes_seq
\setcounter{numc}{0}
\begin{tabular}{n #1}
}
{
\end{tabular}
}
\NewDocumentCommand{\push}{ m }
{
\eiterorm_push:n { #1 }
}
\NewDocumentCommand{\printcomments} { }
{
\begin{tabular}{rl}
\seq_use:Nnnn \g_eiterorm_pushes_seq { \\ } { \\ } { \\ }
\end{tabular}
}
\seq_new:N \g_eiterorm_pushes_seq
\cs_new_protected:Npn \eiterorm_push:n #1
{
\seq_gput_right:Nx \g_eiterorm_pushes_seq { \thenumc. \exp_not:n { & #1 } }
}
\ExplSyntaxOff
\begin{document}
\begin{xtabular}{ l l }
& row1,col2 & row1,col3 \\
& row2,col2 & row2,col3 \push{Comment for row 2.} \\
& row3,col2 & row3,col3 \\
& row4,col2 & row4,col3 \push{Comment for row 4.} \\
& row5,col2 & row5,col3 \push{Comment for row 5.}
\end{xtabular}
\bigskip
\printcomments
\end{document}
注意\push
应该去前终端,\\
因为否则最后一行将启动一个新行,该行将具有初始编号和空内容,并且不final\\
应该出现。
这个想法是\push
添加到稍后被使用的序列中\printcomments
。