使用数组有意义的 & 符号来更改 foreach 循环中的列

使用数组有意义的 & 符号来更改 foreach 循环中的列

我希望循环遍历此代码:

\begin{tabular}{l*{8}c}
    first column &
    column a &
    column b &
    column c &
    column d &
    column e &
    column f &
    column g
\end{tabular}

但下面的代码无法编译:

\begin{tabular}{l*{8}c}
    first column
    \foreach \i in {a,b,c,d,e,f,g,h}{%
        & column \i%
    }
\end{tabular}

出现与我所写内容完全不同的错误:

! Extra }, or forgotten \endgroup.
<template> \unskip \hfil }
                          \hskip \tabcolsep \endtemplate 
l.40         }

我一直希望这个帖子会有所帮助,但我不确定这个问题的这一部分是否最终得到了解答。

我怎样才能使这个循环工作?

答案1

xparse使用and可以得到非常方便的语法expl3。第二个参数代表#1列表中各个项目的占位符。

\documentclass[a4paper]{article}
\usepackage[margin=1.5cm]{geometry}
\usepackage{booktabs}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\firstrow}{mmm}
 {%#1 = first column
  %#2 = format for the other columns
  %#3 = comma separated list of values
  \cs_gset_protected:Nn \__iagolito_temp:n { & #2 }
  #1 \clist_map_function:nN { #3 } \__iagolito_temp:n
 }
\ExplSyntaxOff

\begin{document}

\begin{tabular}{l*{8}c}
\firstrow{first column}{column #1}{a,b,c,d,e,f,g,h} \\
x & 1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 \\
\end{tabular}

\bigskip

\begin{tabular}{l*{8}c}
\toprule
\firstrow{first column}
  {\begin{tabular}[t]{@{}c@{}}column\\ #1\end{tabular}}
  {a,b,c,d,e,f,g,h} \\
\midrule
x & 1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 \\
\bottomrule
\end{tabular}

\end{document}

在此处输入图片描述

答案2

本质上,您无法使用以下方法使其工作\foreach:每个表格单元格都是一个组,&就像}{结束一个组并开始一个新组一样,此时循环的内部状态将丢失。您要么需要一个不需要本地定义的不同循环系统,要么(就像您引用的问题的答案一样)只需使用表格行构建一个宏,然后在循环结束时执行该宏。

这显示了两种机制,请注意,在第二种机制中,循环数据在参数堆栈上进行管理,并且没有进行本地(或全局)定义,这使得在表“内部”执行循环更容易。

在此处输入图片描述

\documentclass[a4paper]{article}
\usepackage{tikz}
\addtolength\textwidth{2in}
\addtolength\oddsidemargin{-1in}
\begin{document}
\small\centering
\def\zz{first column}
    \foreach \i in {a,b,c,d,e,f,g,h}{%
      \xdef\zz{\zz & column \i}%
    }
\begin{tabular}{l*{8}c}
    \zz
\end{tabular}


\def\zzz#1{\zzza#1,\relax}
\def\zzza#1,#2\relax{&column #1\ifx\relax#2\relax\else\expandafter\zzza\fi#2\relax}

\begin{tabular}{l*{8}c}
first column \zzz{a,b,c,d,e,f,g,h}
\end{tabular}




\end{document}

答案3

以下是使用 token 和listofitems

基本上,它从逗号分隔的列表中创建一个标记列表,然后在您需要时调用该标记列表(使用\the\tabrows):

\documentclass{article}
\usepackage{listofitems}
\makeatletter
\newtoks\tabrows
% Command for adding tokens to list
\newcommand\addrowraw[1]{\tabrows\expandafter{\the\tabrows#1}}
% Command that takes a comma separated list
% of items to be in the column of a row
% The second argument is what to do with the current column
% using the \thiscol command:
\newcommand\addrow[2]{
  % Macro to contain the new list
  \def\newrow{}
  % Read argument as list for listofitems
  \readlist\thecolumns{#1}
  % Iterate and append the ampersand and the content of each column
  \foreachitem\thiscol\in\thecolumns{
    \edef\newrow{\unexpanded\expandafter{\newrow}&#2}
  }
  % Remove first ampersand
  \edef\newrow{\expandafter\@gobble\newrow}
  % Just grouping it
  \edef\newrow{{\newrow}}
  \expandafter\addrowraw\newrow
  % Add the \cr
  \addrowraw{\\}
}
\begin{document}
  % These should be _before_ the tabular environment
  \addrow{a,b,c,d,e,f,g,h}{Col \thiscol, r1}
  \addrow{i,j,k,l,m,n,o,p}{Col \thiscol, r2}
  \begin{tabular}{l*{8}c}
     \the\tabrows
  \end{tabular}

\end{document}

在此处输入图片描述

相关内容