![构建表时,如何在 foreach 或条件(或其他组/环境)中使用与号 (&)?](https://linux22.com/image/286137/%E6%9E%84%E5%BB%BA%E8%A1%A8%E6%97%B6%EF%BC%8C%E5%A6%82%E4%BD%95%E5%9C%A8%20foreach%20%E6%88%96%E6%9D%A1%E4%BB%B6%EF%BC%88%E6%88%96%E5%85%B6%E4%BB%96%E7%BB%84%2F%E7%8E%AF%E5%A2%83%EF%BC%89%E4%B8%AD%E4%BD%BF%E7%94%A8%E4%B8%8E%E5%8F%B7%20(%26)%EF%BC%9F.png)
我正在尝试构建一个表格,并且在 tabularx 环境中我想要一个循环,类似于(这里是一个 MWE):
\documentclass[10pt,a4paper]{article}
\usepackage{tabularx}
\usepackage{tikz}
\newcommand{\nRows}{5}
\begin{document}
\begin{tabularx}{\textwidth}{@{}>{\raggedright}p{2.2cm}@{}>{\raggedright}X@{}>{\raggedright}X@{}>{\raggedright}X@{}>{\raggedright}X@{}}
\foreach \r in {1,...,\nRows}{ % https://stackoverflow.com/questions/2561791/iteration-in-latex
\textbf{column1} & two & three & four & five
}
\end{tabularx}
\end{document}
这不起作用,因为 & 符号会造成问题。如果我转义 &s,则整行将与文字 & 符号一起打印在第一列中,类似于:
\documentclass[10pt,a4paper]{article}
\usepackage{tabularx}
\usepackage{tikz}
\newcommand{\nRows}{5}
\begin{document}
\begin{tabularx}{\textwidth}{@{}>{\raggedright}p{2.2cm}@{}>{\raggedright}X@{}>{\raggedright}X@{}>{\raggedright}X@{}>{\raggedright}X@{}}
\foreach \r in {1,...,\nRows}{ % https://stackoverflow.com/questions/2561791/iteration-in-latex
\textbf{column1} \& two \& three \& four \& five
}
\end{tabularx}
\end{document}
得出:
|column1 & | | | |
| two & three & | | | |
| four & five | | | |
而我想要的是:
|column 1 | two | three | four | five |
|column 1 | two | three | four | five |
|column 1 | two | three | four | five |
....
关于如何实现这一点,您有什么想法吗?我实际上并不想制作相同的行 - 行会有所不同。这只是一个 MWE。谢谢!
编辑:我尝试按照评论部分的建议实施 Herbert 的答案。结果没有输出 - 只是一个空白的 PDF。以下是我实施它的方法:
\documentclass[10pt,a4paper]{article}
\usepackage{tabularx}
\usepackage{tikz}
\newcommand{\nRows}{5}
\makeatletter
\newtoks\@tabtoks
\newcommand\addtabtoks[1]{\@tabtoks\expandafter{\the\@tabtoks#1}}
\newcommand*\resettabtoks{\@tabtoks{}}
\newcommand*\printtabtoks{\the\@tabtoks}
\makeatother
\begin{document}
\resettabtoks
\foreach \r in {1,...,\nRows}{ % https://stackoverflow.com/questions/2561791/iteration-in-latex
% \textbf{column1} \& two \& three \& four \& five
\addtabtoks{\textbf{column1} & two & three & four & five \\\hline}%
}
\begin{tabularx}{\textwidth}{@{}>{\raggedright}p{2.2cm}@{}>{\raggedright}X@{}>{\raggedright}X@{}>{\raggedright}X@{}>{\raggedright}X@{}}
\printtabtoks
\end{tabularx}
\end{document}
知道我做错了什么吗?谢谢!
答案1
假设您这样做是因为您希望表的行依赖于循环中的计数器。在这种情况下,您需要一种方法来将扩展的对象添加到标记列表中。在这里,\eaddtabtoks
除了 egreg 对全局分配的更正之外,我还添加了一个宏。
\documentclass[10pt,a4paper]{article}
\usepackage{tabularx,etoolbox}
\usepackage{tikz}
\newcommand{\nRows}{5}
\makeatletter
\newtoks\@tabtoks
\newcommand\addtabtoks[1]{\global\@tabtoks\expandafter{\the\@tabtoks#1}}
\newcommand\eaddtabtoks[1]{\edef\mytmp{#1}\expandafter\addtabtoks\expandafter{\mytmp}}
\newcommand*\resettabtoks{\global\@tabtoks{}}
\newcommand*\printtabtoks{\the\@tabtoks}
\makeatother
\begin{document}
\resettabtoks
\foreach \r in {1,...,\nRows}{
\addtabtoks{\textbf{column 1} &}
\eaddtabtoks{row \r}
\addtabtoks{ & three & four & five \\}%
}
\begin{tabularx}{\textwidth}{@{}>{\raggedright\arraybackslash}p{2.2cm}*{4}{@{}>{\raggedright\arraybackslash}X}@{}}
\printtabtoks
\end{tabularx}%
\end{document}
答案2
\foreach
您忽略了执行组中每个循环的事实,因此当完成它时,更改将\@tabtoks
被撤消。
\global
在相关位置添加(也包括\arraybackslash
在最后一列的规范中,但这是另一个问题)。
\documentclass[10pt,a4paper]{article}
\usepackage{tabularx}
\usepackage{tikz}
\newcommand{\nRows}{5}
\makeatletter
\newtoks\@tabtoks
%%% assignments to \@tabtoks must be global, because they are done in \foreach
\newcommand\addtabtoks[1]{\global\@tabtoks\expandafter{\the\@tabtoks#1}}
%%% variable should always be operated on always locally or always globally
\newcommand*\resettabtoks{\global\@tabtoks{}}
\newcommand*\printtabtoks{\the\@tabtoks}
\makeatother
\begin{document}
\resettabtoks
\foreach \r in {1,...,\nRows}{
\addtabtoks{\textbf{column1} & two & three & four & five \\\hline}%
}
\noindent\begin{tabularx}{\textwidth}{
@{}>{\raggedright}p{2.2cm}
@{}>{\raggedright}X
@{}>{\raggedright}X
@{}>{\raggedright}X
@{}>{\raggedright\arraybackslash}X
@{}
}
\printtabtoks
\end{tabularx}
\end{document}
一个更复杂的例子
假设我们希望每个表行都依赖于循环索引;那么必须进行一些更改。新\addtabtoks
宏采用一个可选参数,如果表达,则应为表示循环中索引的命令\foreach
;在这种情况下,强制参数应为一个参数宏,如下面的代码所示;该参数应为循环索引。
\documentclass[10pt,a4paper]{article}
\usepackage{tabularx}
\usepackage{tikz}
\newcommand{\nRows}{5}
\makeatletter
\newtoks\@tabtoks
%%% assignments to \@tabtoks must be global, because they are done in \foreach
\newcommand\addtabtoks[2][]{%
\if\relax\detokenize{#1}\relax
% no index, just append the second argument
\global\@tabtoks\expandafter{\the\@tabtoks#2}%
\else
% we assume the second argument is a one parameter macro
\global\@tabtoks\expandafter{\the\expandafter\@tabtoks\expandafter#2\expandafter{#1}}%
\fi
}
%%% variable should always be operated on always locally or always globally
\newcommand*\resettabtoks{\global\@tabtoks{}}
\newcommand*\printtabtoks{\the\@tabtoks}
\makeatother
% define a one parameter macro for making the row depending on the current index
\newcommand{\tablerow}[1]{%
\textbf{Row #1} & two & three & four & five \\\hline
}
\begin{document}
\resettabtoks
\foreach \r in {1,...,\nRows}{%
\addtabtoks{\textbf{column1} & two & three & four & five \\\hline}%
}
\noindent\begin{tabularx}{\textwidth}{
@{}>{\raggedright}p{2.2cm}
@{}>{\raggedright}X
@{}>{\raggedright}X
@{}>{\raggedright}X
@{}>{\raggedright\arraybackslash}X
@{}
}
\hline
\printtabtoks
\end{tabularx}
\bigskip
\resettabtoks
\foreach \r in {1,...,\nRows}{%
\addtabtoks[\r]{\tablerow}%
}
\noindent\begin{tabularx}{\textwidth}{
@{}>{\raggedright}p{2.2cm}
@{}>{\raggedright}X
@{}>{\raggedright}X
@{}>{\raggedright}X
@{}>{\raggedright\arraybackslash}X
@{}
}
\hline
\printtabtoks
\end{tabularx}
\end{document}
答案3
如果你愿意在这里使用另一个循环,\foreach
那么还有以下选项,例如\xintFor
从包中新工具。语法有点不同,并且\xintFor
在此处使用并不排除\foreach
在其他地方使用……
更新为热爱前沿技术的人们添加了第二种方法。
\documentclass[10pt,a4paper]{article}
\usepackage{tabularx}
\usepackage{tikz}
\usepackage{xinttools}
\newcommand{\nRows}{5}
% \usepackage{tabu} % alternative to tabularx
\begin{document}
\begin{tabularx}{\textwidth}{@{}>{\raggedright}p{2.2cm}@{}>{\raggedright}X@{}>{\raggedright}X@{}>{\raggedright}X@{}>{\raggedright\arraybackslash}X@{}}
\xintFor* #1 in {\xintSeq {1}{\nRows}}
\do
{(\textsl{row #1}) \textbf{column1} & two & three & four & five
\\ }
\end{tabularx}
% Note with a tabu environment of package tabu, \arraybackslash is not needed
% \begin{tabu} to \textwidth{@{}>{\raggedright}p{2.2cm}@{}>{\raggedright}X@{}>{\raggedright}X@{}>{\raggedright}X@{}>{\raggedright}X@{}}
% \xintFor* #1 in {\xintSeq {1}{\nRows}}
% \do
% {(\textsl{row #1}) \textbf{column1} & two & three & four & five
% \\ }
% \end{tabu}
\end{document}
这是一种依赖于可扩展循环的特殊方法(\xintFor
尽管它享有表格功能,但不可扩展),并且没有计数器!(\xintFor
也不使用计数器)。\xintiloopindex
不能在括号内;并且在这个例子中,我们需要隐藏制表符,以使\xintiloopindex
机制正常工作,因为之前遇到了不可扩展的材料。
\documentclass[10pt,a4paper]{article}
\usepackage{tabularx}
\usepackage{tikz}
\usepackage{xinttools}
\newcommand{\nRows}{5}
\def\TAB{&}
\begin{document}
\begin{tabularx}{\textwidth}{@{}>{\raggedright}p{2.2cm}@{}>{\raggedright}X@{}>{\raggedright}X@{}>{\raggedright}X@{}>{\raggedright\arraybackslash}X@{}}
\xintiloop [1+1]
(\bgroup\slshape row \xintiloopindex\egroup )% \xintiloopindex can not be
% within braces...
\textbf{column1} \TAB two \TAB three \TAB four \TAB five \\
\ifnum\nRows>\xintiloopindex\space
\repeat
\end{tabularx}
\end{document}