答案1
使用的方法xinttools
。
\documentclass{article}
\usepackage[hscale=0.8]{geometry}
\usepackage{array}
\usepackage{xinttools}
\newcommand{\peopleA}[1]{%
% first we trim leading and trailing spaces from each item
% #1 maybe a macro, it will be expanded; this means first item
% will be expanded. Prefix this item with a space is this is to
% be avoided
\oodef\peopleAlist{\xintCSVtoList{#1}}%
% now build an array for easy access
\xintAssignArray\peopleAlist\to\peopleAarray
}%
\newcommand{\peopleB}[1]{%
\oodef\peopleBlist{\xintCSVtoList{#1}}%
\xintAssignArray\peopleBlist\to\peopleBarray
}%
\newcommand{\peopletable}{%
% say we have Na people of type A and Nb people of type B
% I think from the OP, it is asked to always use three rows
% from 0 to 3 people of given type, 1 column
% from 4 to 6 people, 2 columns
% from 7 to 9 people, 3 columns
% We do the arithmetic in TeX, not using packages
\begingroup
\count0 \peopleAarray{0}
\advance\count0 by 2
\divide \count0 by 3
\ifnum\count0=0 \advance\count0 by 1 \fi
\edef\peopletableNbOfColsA{\the\count0}%
\count2 \peopleBarray{0}
\advance\count2 by 2
\divide \count2 by 3
\ifnum\count2=0 \advance\count2 by 1 \fi
\edef\peopletableNbOfColsB{\the\count2}%
\count4 = \count0
\advance\count4 by \count2
\edef\peopletableNbOfCols{\the\count4}%
%\show\peopletableNbOfCols
\edef\peopletableColIndices{\xintSeq{1}{\peopletableNbOfCols}}%
%\show\peopletableColIndices
\centering
\begin{tabular}{|*{\peopletableNbOfCols}{l|}}%
\hline
\multicolumn{\peopletableNbOfCols}{|c|}{\textbf{Title}}\\
\hline
\multicolumn{\peopletableNbOfColsA}{|l|}{PeopleA}&
\multicolumn{\peopletableNbOfColsB}{l|}{PeopleB}\\
\hline
% first row
\xintFor* ##1 in {\peopletableColIndices}:
{\xintifForFirst{}{&}%
\ifnum##1>\peopletableNbOfColsA\space
\unless\ifnum\numexpr3*(##1-\peopletableNbOfColsA)-2>\peopleBarray{0}
% unfortunately xinttools create arrays checking
% "index-out-of-range" type of errors, instead
% of silently expanding to nothing, hence the check above
\peopleBarray{3*(##1-\peopletableNbOfColsA)-2}%
\fi
\else
\unless\ifnum\numexpr3*##1-2>\peopleAarray{0}
\peopleAarray{3*##1-2}%
\fi
\fi
}\\
\hline
% second row
\xintFor* ##1 in {\peopletableColIndices}:
{\xintifForFirst{}{&}%
\ifnum##1>\peopletableNbOfColsA\space
\unless\ifnum\numexpr3*(##1-\peopletableNbOfColsA)-1>\peopleBarray{0}
% unfortunately xinttools create arrays checking
% "index-out-of-range" type of errors, instead
% of silently expanding to nothing, hence the check above
\peopleBarray{3*(##1-\peopletableNbOfColsA)-1}%
\fi
\else
\unless\ifnum\numexpr3*##1-1>\peopleAarray{0}
\peopleAarray{3*##1-1}%
\fi
\fi
}\\
\hline
% third row
\xintFor* ##1 in {\peopletableColIndices}:
{\xintifForFirst{}{&}%
\ifnum##1>\peopletableNbOfColsA\space
\unless\ifnum\numexpr3*(##1-\peopletableNbOfColsA)>\peopleBarray{0}
% unfortunately xinttools create arrays checking
% "index-out-of-range" type of errors, instead
% of silently expanding to nothing, hence the check above
\peopleBarray{3*(##1-\peopletableNbOfColsA)}%
\fi
\else
\unless\ifnum\numexpr3*##1>\peopleAarray{0}
\peopleAarray{3*##1}%
\fi
\fi
}\\
\hline
\end{tabular}%
\par
\endgroup
}
\begin{document}
\peopleA{P. Smith, A. Row, B. Streams, O. Green, L. Handley}
\peopleB{A. Hause, J. Ring}
\peopletable
\bigskip
With only three rows we soon get wide tables, so let's use digits for
demonstration purposes:
\peopleA{P. Smith, A. Row, B. Streams, O. Green, L. Handley,
6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}
\peopleB{A. Hause, J. Ring, 3, 4, 5, 6, 7, 8, 9, 10}
\peopletable
\end{document}
(空列时可正常工作)
OP 要求表格占据整个文本宽度,可以用来实现tabularx
。
\documentclass{article}
\usepackage{geometry}
\usepackage{array}
\usepackage{tabularx}
\usepackage{xinttools}
\newcommand{\peopleA}[1]{%
% first we trim leading and trailing spaces from each item
% #1 maybe a macro, it will be expanded; this means first item
% will be expanded. Prefix this item with a space is this is to
% be avoided
\oodef\peopleAlist{\xintCSVtoList{#1}}%
% now build an array for easy access
\xintAssignArray\peopleAlist\to\peopleAarray
}%
\newcommand{\peopleB}[1]{%
\oodef\peopleBlist{\xintCSVtoList{#1}}%
\xintAssignArray\peopleBlist\to\peopleBarray
}%
\newcommand{\peopletable}{%
% say we have Na people of type A and Nb people of type B
% I think from the OP, it is asked to always use three rows
% from 0 to 3 people of given type, 1 column
% from 4 to 6 people, 2 columns
% from 7 to 9 people, 3 columns
% We do the arithmetic in TeX, not using packages
\begingroup
\count0 \peopleAarray{0}
\advance\count0 by 2
\divide \count0 by 3
\ifnum\count0=0 \advance\count0 by 1 \fi
\edef\peopletableNbOfColsA{\the\count0}%
\count2 \peopleBarray{0}
\advance\count2 by 2
\divide \count2 by 3
\ifnum\count2=0 \advance\count2 by 1 \fi
\edef\peopletableNbOfColsB{\the\count2}%
\count4 = \count0
\advance\count4 by \count2
\edef\peopletableNbOfCols{\the\count4}%
%\show\peopletableNbOfCols
\edef\peopletableColIndices{\xintSeq{1}{\peopletableNbOfCols}}%
%\show\peopletableColIndices
\noindent
\begin{tabularx}{\linewidth}{|*{\peopletableNbOfCols}{X|}}%
\hline
\multicolumn{\peopletableNbOfCols}{|c|}{\textbf{Title}}\\
\hline
\multicolumn{\peopletableNbOfColsA}{|l|}{PeopleA}&
\multicolumn{\peopletableNbOfColsB}{l|}{PeopleB}\\
\hline
% first row
\xintFor* ##1 in {\peopletableColIndices}:
{\xintifForFirst{}{&}%
\ifnum##1>\peopletableNbOfColsA\space
\unless\ifnum\numexpr3*(##1-\peopletableNbOfColsA)-2>\peopleBarray{0}
% unfortunately xinttools create arrays checking
% "index-out-of-range" type of errors, instead
% of silently expanding to nothing, hence the check above
\peopleBarray{3*(##1-\peopletableNbOfColsA)-2}%
\fi
\else
\unless\ifnum\numexpr3*##1-2>\peopleAarray{0}
\peopleAarray{3*##1-2}%
\fi
\fi
}\\
\hline
% second row
\xintFor* ##1 in {\peopletableColIndices}:
{\xintifForFirst{}{&}%
\ifnum##1>\peopletableNbOfColsA\space
\unless\ifnum\numexpr3*(##1-\peopletableNbOfColsA)-1>\peopleBarray{0}
% unfortunately xinttools create arrays checking
% "index-out-of-range" type of errors, instead
% of silently expanding to nothing, hence the check above
\peopleBarray{3*(##1-\peopletableNbOfColsA)-1}%
\fi
\else
\unless\ifnum\numexpr3*##1-1>\peopleAarray{0}
\peopleAarray{3*##1-1}%
\fi
\fi
}\\
\hline
% third row
\xintFor* ##1 in {\peopletableColIndices}:
{\xintifForFirst{}{&}%
\ifnum##1>\peopletableNbOfColsA\space
\unless\ifnum\numexpr3*(##1-\peopletableNbOfColsA)>\peopleBarray{0}
% unfortunately xinttools create arrays checking
% "index-out-of-range" type of errors, instead
% of silently expanding to nothing, hence the check above
\peopleBarray{3*(##1-\peopletableNbOfColsA)}%
\fi
\else
\unless\ifnum\numexpr3*##1>\peopleAarray{0}
\peopleAarray{3*##1}%
\fi
\fi
}\\
\hline
\end{tabularx}%
\par
\endgroup
}
\begin{document}
\peopleA{P. Smith, A. Row, B. Streams, O. Green, L. Handley}
\peopleB{A. Hause, J. Ring}
\peopletable
\bigskip
With only three rows we soon get wide tables, so let's use digits for
demonstration purposes:
\peopleA{P. Smith, A. Row, B. Streams, O. Green, L. Handley,
6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}
\peopleB{A. Hause, J. Ring, 3, 4, 5, 6, 7, 8, 9, 10}
\peopletable
\bigskip
\peopleA{}
\peopleB{}
\peopletable
\end{document}