根据列表和列数生成表格

根据列表和列数生成表格

有时,会使用一张桌子来压缩大量的物品。

例子:

a b c d
e f g h
j k l

而不是单独列出所有项目。

我们想要定义一个命令来简化这一操作的实现(比如说你想插入一个项目i,但你不想进行所有的记账工作来让这些项目再次匹配)。

我们想要定义一个\compacttable{cccc}{a,b,c,d,e,f,g,h,j,k,l}显示此类表格的命令。

我们尝试了以下定义:

\usepackage{tikz,ifthen,xstring,etoolbox}

\newcounter{col}
\newcommand{\compacttable}[2]{
    \setcounter{colc}{1}\StrLen{#1}[\imresl]
    \def\temp{}
    \foreach\tx in{#2}{
    \ifthenelse{\equal{\imresl}{\value{colc}}}{
        \setcounter{colc}{1}\expandafter\gdef\expandafter\temp\expandafter{\temp \tx \\}
    }{
        \stepcounter{colc}\expandafter\gdef\expandafter\temp\expandafter{\temp \tx & }
    }}
    \begin{tabular}{#1}
    \temp{}
    \end{tabular}
}

但是,那平均能量损失未能显示任何值:

main.tex

\documentclass{article}
\usepackage{tikz,ifthen,xstring,etoolbox}
\newcounter{col}
\newcommand{\compacttable}[2]{
    \setcounter{colc}{1}\StrLen{#1}[\imresl]
    \def\temp{}
    \foreach\tx in{#2}{
    \ifthenelse{\equal{\imresl}{\value{colc}}}{
        \setcounter{colc}{1}\expandafter\gdef\expandafter\temp\expandafter{\temp \tx \\}
    }{
        \stepcounter{colc}\expandafter\gdef\expandafter\temp\expandafter{\temp \tx & }
    }}
    \begin{tabular}{#1}
    \end{tabular}
}
\begin{document}
\compacttable{cccc}{a,b,c,d,e,f,g,h,j,k,l}
\end{document}

我们认为这是由于\tx当我们尝试扩展时不受约束所致\temp

答案1

无需额外的软件包,使用标记列表即可轻松添加各种 TeX 标记:

\documentclass{article}
\newcounter{col} \newcounter{maxcol} \newtoks\myTab
\makeatletter
\newcommand\addtabtoks[1]{\myTab\expandafter{\the\myTab#1}}
\newcommand\compacttable[2]{%
  \setcounter{col}{0}\setcounter{maxcol}{#1}%
  \myTab{\tabular{*#1c}}%                       Initial setting
  \compacttable@i#2,,\@nil}
\def\compacttable@i#1,#2,#3\@nil{%
  \stepcounter{col}%
  \ifnum\thecol<\themaxcol\addtabtoks{ #1 & }%  Default column
  \else \addtabtoks{#1 \\}\setcounter{col}{0}\fi% start new line
  \ifx\relax#2\relax \the\myTab\endtabular%     Output of list and \endtabular  
  \else \compacttable@i#2,#3\@nil\fi}
\makeatother
\begin{document}
\compacttable4{a,b,c,d,e,f,g,h,j,k,l}
\fbox{\compacttable3{a,b,c,d,e,f,g,h,j,k,l}}
\end{document}

enter image description here

答案2

正如你所指出的,问题是由于扩张造成的。你可以做就是了:

\expandafter\expandafter\expandafter\gdef\expandafter\expandafter\expandafter\temp\expandafter\expandafter\expandafter{\expandafter\temp\tx & }%

但是,为了提高可读性,可以定义一个中间宏来减少 的多次使用,\expandafter如下所示。此外,代码需要%在许多行后面以 和 结尾{}以防止在文档中插入空格。

\documentclass[border=5]{standalone}
\usepackage{pgffor,ifthen,xstring}
\newcounter{colc}
\def\globalappendtomacro#1#2{%
  \expandafter\gdef\expandafter#1\expandafter{#1#2}%
}
\newcommand{\compacttable}[2]{%
    \setcounter{colc}{1}%
    \StrLen{#1}[\imresl]%
    \def\temp{}%
    \foreach\tx in{#2}{%
      \ifthenelse{\equal{\imresl}{\value{colc}}}{%
        \setcounter{colc}{1}%
        \expandafter\globalappendtomacro\expandafter\temp\expandafter{\tx \\}%
    }{%
        \stepcounter{colc}%
        \expandafter\globalappendtomacro\expandafter\temp\expandafter{\tx &}%
     }}%
    \begin{tabular}{#1}
      \temp
    \end{tabular}%
}

\begin{document}
\framebox{\compacttable{cccc}{a,b,c,d,e,f,g,h,j,k,l}}
\end{document}

enter image description here

答案3

这是一个expl3实现;按顺序保存输入并进行映射;如果列数等于指定的列数,则添加\\并将列计数器清零,否则只需添加&

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\compacttable}{ m m }
 {
  \commusoft_compact_table:nn { #1 } { #2 }
 }

\int_new:N \l__commusoft_col_int
\tl_new:N \l__commusoft_table_body_tl
\seq_new:N \l__commusoft_input_seq

\cs_new_protected:Npn \commusoft_compact_table:nn #1 #2
 {
  \tl_clear:N \l__commusoft_table_body_tl
  \int_zero:N \l__commusoft_col_int
  \seq_set_split:Nnn \l__commusoft_input_seq { , } { #2 }
  \seq_map_inline:Nn \l__commusoft_input_seq
   {
    \int_incr:N \l__commusoft_col_int
    \int_compare:nTF { \l__commusoft_col_int == #1 }
     {
      \tl_put_right:Nn \l__commusoft_table_body_tl { ##1 \\ }
      \int_zero:N \l__commusoft_col_int
     }
     {
      \tl_put_right:Nn \l__commusoft_table_body_tl { ##1 & }
     }
   }
  \begin{tabular}{*{#1}{c}}
  \l__commusoft_table_body_tl
  \end{tabular}
 }
\ExplSyntaxOff

\begin{document}

\compacttable{4}{a,b,c,d,e,f,g,h,j,k,l}

\compacttable{5}{a,b,c,d,e,f,g,h,i,j,k,l,m}

\end{document}

enter image description here

使用在第一次编写答案时尚未提供的功能来进行更直接的实现。

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\compacttable}{ m m }
 {
  \commusoft_compact_table:nn { #1 } { #2 }
 }

\seq_new:N \l__commusoft_input_seq

\cs_new_protected:Nn \commusoft_compact_table:nn
 {
  % split the input at commas
  \seq_set_split:Nnn \l__commusoft_input_seq { , } { #2 }
  % define an auxiliary function to store the number of columns
  \cs_set_protected:Nn \__commusoft_item:nn
   {% ##1 is the current index, ##2 is the current item
    ##2
    \int_compare:nTF { \int_mod:nn { ##1 } { #1 } == 0 } { \\ } { & }
   }
  % make the table by mapping the sequence
  \begin{tabular}{*{#1}{c}}
  \seq_map_indexed_function:NN \l__commusoft_input_seq \__commusoft_item:nn
  \end{tabular}
 }
\ExplSyntaxOff

\begin{document}

\compacttable{4}{a,b,c,d,e,f,g,h,j,k,l}

\compacttable{5}{a,b,c,d,e,f,g,h,i,j,k,l,m}

\end{document}

相关内容