![平衡多列列表?](https://linux22.com/image/419005/%E5%B9%B3%E8%A1%A1%E5%A4%9A%E5%88%97%E5%88%97%E8%A1%A8%EF%BC%9F.png)
我想平衡 N 列的列表,以便最小垂直空间。从其他类似的问题中,经过一番挣扎,我写了这篇文章:
\documentclass{article}
\usepackage[balancingshow]{multicol}
\usepackage{regexpatch}
\usepackage{lipsum}
\usepackage{enumitem}
\usepackage{expl3}
\usepackage{xparse}
\usepackage{keyval}
\newcounter{multicolminlines}
\setcounter{multicolminlines}{1}
\makeatletter
\xpatchcmd\balance@columns
{\ifnum\dimen@<\topskip
\mult@info\@ne
{Start value
\the\dimen@ \space ->
\the\topskip \space (corrected)}%
\dimen@\topskip
\fi}
{\skip@\c@multicolminlines\baselineskip
\advance\skip@-\baselineskip
\advance\skip@\topskip
\ifnum\dimen@<\skip@
\mult@info\@ne
{Start value
\the\dimen@ \space ->
\the\skip@ \space (corrected)}%
\dimen@\skip@
\fi
}
{\typeout{Success!}}{\patchFAILED}
\define@key{hlist@keys}{columns}{\def\hlist@columns{#1}}%
\define@key{hlist@keys}{minlines}{\def\hlist@minlines{#1}}%
\newcommand{\fixspacing}{\vspace{0pt plus 1filll}\mbox{}}
\newenvironment{hlist}[1][]{%
\setkeys{hlist@keys}{columns=4,minlines=4,#1}
\setcounter{multicolminlines}{\hlist@minlines}
\begin{multicols}{\hlist@columns}
}{
\fixspacing
\end{multicols}
}
\makeatother
\begin{document}
\lipsum[1-2]
\begin{hlist}[columns=3,minlines=10]
\begin{itemize}
\item Gods \item Óðinn \item Baldur \item Njörður \item Freyr
\item Týr \item Bragi \item Heimdal \item Thor \item Höðr
\item Víðar \item Áli or Váli \item Ullr \item Óðinn \item Þór
\item Njörðr \item Freyr \item Týr \item Heimdal \item Bragi
\item Víðar \item Váli \item Ullr \item Hœnir
\end{itemize}
\end{hlist}
\lipsum[3-4]
\end{document}
但是,正如您所见,它并不总是有效。在此示例中,可以通过使用第三列上剩余的两个案例来节省一行。
这能让它 100% 正常工作吗?
答案1
我不能 100% 确定我理解了你试图做的事情,因为这似乎是矛盾的。一方面,你的代码试图强制执行最少的行数(示例中为 10 行),但你却写道
但是,正如您所见,它并不总是有效。在此示例中,可以通过使用第三列上剩余的两个案例来节省一行。
这能让它 100% 正常工作吗?
让什么 100% 始终有效?默认情况下,多列会平衡到最短的垂直高度,因此如果您在不使用补丁的情况下使用它,则每列中会恰好有 8 个项目。但由于您要求列至少为 10*\baselineskip,因此您会得到 9 个项目,因为这些项目适合您所要求的垂直尺寸。
因此,您想要的规范似乎不太清楚。
不管怎样: multicols 已经支持你试图实现的,它调用了 counter minrows
。所以你可以放弃你的补丁,只需使用
\makeatletter
\define@key{hlist@keys}{columns}{\def\hlist@columns{#1}}%
\define@key{hlist@keys}{minlines}{\def\hlist@minlines{#1}}%
\newenvironment{hlist}[1][]{%
\setkeys{hlist@keys}{columns=4,minlines=4,#1}%
\setcounter{minrows}{\hlist@minlines}%
\begin{multicols}{\hlist@columns}%
}{\end{multicols}}
\makeatother
比你多几个%
s 可以避免输出中出现虚假空格。你实际上并不需要,\fixspacing
因为 multicol 提供了处理最后一列的参数。
所以在我看来,一切似乎都井然有序。如果不是,请更详细地解释一下你所追求的算法行为。
最后一点,minrows
或你的minlines
是指普通文本行的高度,因此要请求第一列至少 10 个项目,您需要将其设置得明显高于 10。
更新
由于我删除了您的 \fixedspacing 命令(因为它应该是必需的),所以我没有注意到它以 \mbox 结尾。因此,您实际上在多列中添加了另一行,这样您就有了 3x8 个项目 + 一行。这无法平衡为 8 +8 +8,自然会变成 9 + 9 + 7(因为我们实际上在最后一列中有这条不可见的额外行)。