11

I want a command like

\mytable{4}{ a & b & c & d & e & f}

would be the same as

\begin{tabular}{cccc}
a & b & c & d\\
e & f\\
\end{tabular}

and

\mytable{2}{ a & b & c & d & e & f}

would be the same as

\begin{tabular}{cc}
a & b\\
c & d\\
e & f\\
\end{tabular}
  • 1
    Should this also work for a number higher than 9? – Qrrbrbirlbel Jul 15 '13 at 1:31
  • It is ok with me if it works only for 1 through 9. – Mark S. Jul 15 '13 at 1:32
  • 1
    Somehow the matrix environment manages this, and I've never understood how (and am not experienced enough with the LaTeX source to go scrobbling in it). Could anyone explain? – LSpice Jul 15 '13 at 2:40
  • @LSpice the ams matrix environment doesn't insert \\ it just makes a wide table with a pre-specified number of columns. – David Carlisle Jul 15 '13 at 8:16
12

Here is a solution that uses a delimited macro and a counter.

Code

\documentclass{article}
\newcounter{mytable@count}
\makeatletter
\newcommand{\mytable}[2]{%
  \edef\mytable@count@{#1}%
  \setcounter{mytable@count}{0}%
  \begin{tabular}{*{#1}{c}}
    \strip@ampersand#2&\@nil
  \end{tabular}
}
\def\strip@ampersand#1&#2\@nil{%
  #1%
  \if\relax\detokenize{#2}\relax
    \expandafter\@gobble
  \else
    \expandafter\@firstofone
  \fi
  {%
    \stepcounter{mytable@count}%
    \ifnum\value{mytable@count}<\mytable@count@\relax
      \expandafter\@firstoftwo
    \else
      \expandafter\@secondoftwo
    \fi
    {&}
    {\\\noalign{\setcounter{mytable@count}{0}}}%
    \strip@ampersand#2\@nil
  }%
}
\makeatother

\begin{document}
\mytable{4}{ a & b & c & d & e & f}

\hrulefill

\mytable{2}{ a & b & c & d & e & f}
\end{document}

Output

enter image description here

4

An expl3 solution. I add an optional argument for specifying a different entry delimiter and also one for different column alignments.

\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\mytable}{O{&} m O{c} m}
 {% #1 = inner delimiter (optional}
  % #2 = number of columns
  % #3 = alignment (optional)
  % #4 = table body
  \egreg_mytable:nnnn { #1 } { #2 } { #3 } { #4 }
 }

\seq_new:N \l__egreg_tablebody_seq
\tl_new:N \l__egreg_tablebody_tl
\int_new:N \l__egreg_step_int

\cs_new_protected:Npn \egreg_mytable:nnnn #1 #2 #3 #4
 {
  % store the body in a sequence
  \seq_set_split:Nnn \l__egreg_tablebody_seq { #1 } { #4 }
  \int_zero:N \l__egreg_step_int
  \tl_clear:N \l__egreg_tablebody_tl
  % build the real table body
  \seq_map_inline:Nn \l__egreg_tablebody_seq
   {
    % increment the counter
    \int_incr:N \l__egreg_step_int
    % add an entry
    \tl_put_right:Nn \l__egreg_tablebody_tl { ##1 }
    % add \\ if we are done for a row, else add &
    % we just compute the remainder of the division by #2
    \int_compare:nTF { \int_mod:nn { \l__egreg_step_int } { #2 } = 0 }
     { \tl_put_right:Nn \l__egreg_tablebody_tl { \\ } }
     { \tl_put_right:Nn \l__egreg_tablebody_tl { & } }
   }
  % produce the table
  \begin{tabular}{*{#2}{#3}}
  \l__egreg_tablebody_tl
  \end{tabular}
 }

\ExplSyntaxOff
\begin{document}

\mytable{4}{ a & b & c & d & e & f}

\medskip

\mytable{2}{ a & b & c & d & e & f}

\medskip

\mytable[,]{3}{a, b, c, d, e, f}

\medskip

\mytable[;]{3}[l]{aaa; bb; ccc; dddddd; e; f}

\medskip

\mytable[;]{3}[lr]{aaa; bb; ccc; dddddd; e; f}

\end{document}

enter image description here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.