有时,会使用一张桌子来压缩大量的物品。
例子:
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}
答案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}
答案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}
使用在第一次编写答案时尚未提供的功能来进行更直接的实现。
\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}