带有计数器和左对齐标签的嵌套列表

带有计数器和左对齐标签的嵌套列表

目前,我使用三个用户定义列表的组合来实现这一点。其中两个(examlist用于一位数标签,以及exxamlist用于两位数标签)控制顶级项目。第三个(examlistii)控制两种顶级情况的子级项目。

效果(如下所示)正是我想要的。但是,方法似乎有些野蛮。我想使用“单一”列表来实现这一点,也许可以使用“enumitem”包,但我似乎无法使用列表键来实现这一目的。任何帮助都将不胜感激。

\documentclass{article}

%examlist
\newcounter{exami}
\newenvironment{examlist}
{\begin{list}{\arabic{exami}.\hfill}
{\usecounter{exami}
\setlength{\labelwidth}{3ex}
\setlength{\labelsep}{0ex}
\setlength{\leftmargin}{3ex}}}
{\end{list}}

%exxamlist
\newcounter{exxam}
\newenvironment{exxamlist}
{\begin{list}{\arabic{exxam}.\hfill}
{\usecounter{exxam}\setcounter{exxam}{9}
\setlength{\labelwidth}{4.2ex}
\setlength{\labelsep}{0ex}
\setlength{\leftmargin}{4.2ex}}}
{\end{list}}

%examlistii
\newcounter{examii} 
\newenvironment{examlistii}
{\begin{list}{\alph{examii})\hfill}
{\usecounter{examii}
\setlength{\labelwidth}{3ex} 
\setlength{\labelsep}{0ex}
\setlength{\leftmargin}{3ex}}}
{\end{list}}

\begin{document}
\noindent
This is the surrounding text. The following list has flush-left labels.   

\begin{examlist}
  \item Problem 1
  \item Problem 2

  \begin{examlistii}
    \item Part (a)
    \item Part (b)
  \end{examlistii}

  \item Problem 3
\end{examlist}

\begin{exxamlist}
  \item Problem 10

  \begin{examlistii}
    \item Part (a)
    \item Part (b)
  \end{examlistii}

  \item Problem 11
\end{exxamlist}
\end{document}

答案1

以下是您的列表enumitem

\documentclass{article}
\usepackage{enumitem}
%examlist
\newlist{examlist}{enumerate}{1}
\setlist[examlist,1]{
  align=left,
  labelwidth=1.5em,
  labelsep=0pt,
  leftmargin=1.5em,
  label=\arabic*.,
}
\newlist{exxamlist}{enumerate}{1}
\setlist[exxamlist,1]{
  align=left,
  labelwidth=2em,
  labelsep=0pt,
  leftmargin=2em,
  label=\arabic*.,
  before=\setcounter{exxamlisti}{9},
}

%examlistii
\newlist{examlistii}{enumerate}{1}
\setlist[examlistii,1]{
  align=left,
  labelwidth=1.5em,
  labelsep=0pt,
  leftmargin=1.5em,
  label=\alph*),
  nosep,
}

\begin{document}
\noindent
This is the surrounding text. The following list has flush-left labels.   

\begin{examlist}
  \item Problem 1
  \item Problem 2

  \begin{examlistii}
    \item Part (a)
    \item Part (b)
  \end{examlistii}

  \item Problem 3
\end{examlist}

\begin{exxamlist}
  \item Problem 10

  \begin{examlistii}
    \item Part (a)
    \item Part (b)
  \end{examlistii}

  \item Problem 11
\end{exxamlist}
\end{document}

在此处输入图片描述

我只是将 ex 单位改为 em,这对于水平测量更合适。数字通常为 0.5em 宽。

您只需一个环境即可完成工作:

\documentclass{article}
\usepackage{enumitem}

\newlist{examlist}{enumerate}{2}
\setlist[examlist,1]{
  align=left,
  labelwidth=2em,
  labelsep=0pt,
  leftmargin=2em,
  label=\protect\makebox[1em][r]{\arabic*}.,
  ref=\arabic*,
}
\setlist[examlist,2]{
  align=left,
  labelwidth=2em,
  labelsep=0pt,
  leftmargin=2em,
  label=\alph*),
  nosep,
}

\begin{document}
\noindent
This is the surrounding text. The following list has flush-left labels.   

\begin{examlist}
  \item Problem 1
  \item Problem 2

  \begin{examlist}
    \item Part (a)
    \item Part (b)
  \end{examlist}

  \item Problem 3
\end{examlist}

\begin{examlist}\setcounter{examlisti}{8}
  \item Problem 9 

  \item Problem 10

  \begin{examlist}
    \item Part (a)
    \item Part (b)
  \end{examlist}

  \item Problem 11
\end{examlist}
\end{document}

问题是列表项少于 9 个。可以设想一种机制来检查给定列表项是否超过 9 个,并(在下一次传递时)调整参数来处理这个问题。但这会产生不同的问题列表,甚至可能在对开页上。

这是最终环境中的结果,编号从 9 开始以显示效果。

在此处输入图片描述

为了完整起见,这里给出的解决方案是,如果列表的项目少于九个,则数字向左对齐;如果列表的项目多于九个,则只有两位数的数字向左对齐。

\documentclass{article}
\usepackage{enumitem,refcount}

\makeatletter
\newlist{xexamlist}{enumerate}{2}
\setlist[xexamlist,1]{
  align=left,
  labelwidth=\examlist@margin,
  labelsep=0pt,
  leftmargin=\examlist@margin,
  label=\protect\makebox[\examlist@label][r]{\arabic*}.,
  ref=\arabic*,
}
\setlist[xexamlist,2]{
  align=left,
  labelwidth=2em,
  labelsep=0pt,
  leftmargin=2em,
  label=\alph*),
  nosep,
}

\newif\if@examlist
\newcounter{count@examlist}
\newenvironment{examlist}
 {\if@examlist
    \@examlistfalse
  \else
    \setup@examlist\@examlisttrue
  \fi
  \xexamlist}
 {\if@examlist\else
    \edef\@currentlabel{\the\value{xexamlisti}}%
    \label{examlist@@@\thecount@examlist}%
  \fi
  \endxexamlist}
\def\setup@examlist{%
  \stepcounter{count@examlist}%
  \ifnum\getrefnumber{examlist@@@\thecount@examlist}>9
    \def\examlist@margin{2em}%
    \def\examlist@label{1em}%
  \else
    \def\examlist@margin{1.5em}%
    \def\examlist@label{.5em}%
  \fi
}
\makeatother

\begin{document}
\noindent
This is the surrounding text. The following list has flush-left labels.   

\begin{examlist}
  \item Problem 1
  \item Problem 2

  \begin{examlist}
    \item Part (a)
    \item Part (b)
  \end{examlist}

  \item Problem 3
\end{examlist}

\begin{examlist}\setcounter{xexamlisti}{8}
  \item Problem 9

  \item Problem 10

  \begin{examlist}
    \item Part (a)
    \item Part (b)
  \end{examlist}

  \item Problem 11
\end{examlist}
\end{document}

在此处输入图片描述

答案2

是的,enumitem可以快速完成。可以使用以下方法全局修改这两个嵌套列表

\usepackage{enumitem,showframe}
\setlist[enumerate,1]{
  label={\arabic*.},
  ref={\arabic*},
  labelindent=0pt,
  widest={10.},
  leftmargin=*,
  align=left}
\setlist[enumerate,2]{
  label={\alph*)}, 
  ref={\alph*}}

这会将第一enumerate级编号/标签(和引用,如果需要)设置为\arabic.,而第二级设置为\alph)

在此处输入图片描述

\documentclass{article}
\usepackage{enumitem,showframe}
\setlist[enumerate,1]{
  label={\arabic*.},
  ref={\arabic*},
  labelindent=0pt,
  widest={10.},
  leftmargin=*,
  align=left}
\setlist[enumerate,2]{
  label={\alph*)}, 
  ref={\alph*}}

\begin{document}
This is the surrounding text. The following list has flush-left labels.   

\begin{enumerate}
  \item Problem~1

  \item Problem~2

  \begin{enumerate}
    \item Part~(a)

    \item Part~(b)
  \end{enumerate}

  \item Problem~3

  \setcounter{enumi}{9}% Just for this example

  \item Problem~10

  \begin{enumerate}
    \item Part~(a)

    \item Part~(b)
  \end{enumerate}

  \item Problem~11
\end{enumerate}
\end{document}

您还可以使用 创建自己的列表名称\newlist。请参阅enumitem文档了解更多信息。


在我看来,没有必要使用不同的缩进。不过这里有一种方法可以实现这一点:

在此处输入图片描述

\documentclass{article}
\usepackage{enumitem,showframe}
\newlist{exami}{enumerate}{1}
\setlist[exami,1]{
  label={\arabic*.},
  ref={\arabic*},
  labelindent=0pt,
  widest={9.},
  leftmargin=*,
  align=left}
\newlist{examii}{enumerate}{1}
\setlist[examii,1]{
  label={\alph*)}, 
  ref={\alph*}}

\newlength{\indentdiff}
\setlength{\indentdiff}{1.2ex}

\makeatletter
\let\olditem\item
\renewcommand{\item}{%
  \ifnum\pdfstrcmp{\@enumctr}{examii}=0
    \ifnum\value{examii}<9
      \olditem
    \else
      \end{exami}
      \begin{exami}[widest={10.}, start=10]
        \olditem
        \let\item\olditem
    \fi
  \else
    \olditem
  \fi
}
\makeatother

\begin{document}
This is the surrounding text. The following list has flush-left labels.   

\begin{exami}
  \item Problem~1 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce 
  dictum lacus velit, et malesuada enim fringilla eget. Nulla id sem eget odio fringilla 
  ornare ac non urna. Phasellus id sem tincidunt, posuere ante sed, efficitur risus. 
  Phasellus sagittis augue non diam lacinia volutpat. Duis tempus arcu nec arcu porttitor, 
  sit amet gravida velit pretium.

  \item Problem~2 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce 
  dictum lacus velit, et malesuada enim fringilla eget. Nulla id sem eget odio fringilla 
  ornare ac non urna. Phasellus id sem tincidunt, posuere ante sed, efficitur risus. 
  Phasellus sagittis augue non diam lacinia volutpat. Duis tempus arcu nec arcu porttitor, 
  sit amet gravida velit pretium.

  \begin{examii}
    \item Part~(a)

    \item Part~(b)
  \end{examii}

  \item Problem~3 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce 
  dictum lacus velit, et malesuada enim fringilla eget. Nulla id sem eget odio fringilla 
  ornare ac non urna. Phasellus id sem tincidunt, posuere ante sed, efficitur risus. 
  Phasellus sagittis augue non diam lacinia volutpat. Duis tempus arcu nec arcu porttitor, 
  sit amet gravida velit pretium.

  \setcounter{examii}{9}% Just for this example

  \item Problem~10 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce 
  dictum lacus velit, et malesuada enim fringilla eget. Nulla id sem eget odio fringilla 
  ornare ac non urna. Phasellus id sem tincidunt, posuere ante sed, efficitur risus. 
  Phasellus sagittis augue non diam lacinia volutpat. Duis tempus arcu nec arcu porttitor, 
  sit amet gravida velit pretium.

  \begin{examii}
    \item Part~(a)

    \item Part~(b)
  \end{examii}

  \item Problem~11 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce 
  dictum lacus velit, et malesuada enim fringilla eget. Nulla id sem eget odio fringilla 
  ornare ac non urna. Phasellus id sem tincidunt, posuere ante sed, efficitur risus. 
  Phasellus sagittis augue non diam lacinia volutpat. Duis tempus arcu nec arcu porttitor, 
  sit amet gravida velit pretium.
\end{exami}
\end{document}

背后的想法解决方案是重新定义\item关闭现有exami环境并重新启动一个具有略微不同参数的新环境(widest={10.}start=10),然后重新定义为原始环境\item\olditem)。

以下是重新定义的伪代码表示\item

We will need the current definition of \item later, so 
  make a duplicate of \item and store it in \olditem (\let\olditem\item)
With a copy stored, change \item to now do the following:
  if (the enumeration counter being used is "examii") then
    if (the value of counter "examii" < 9) then
      \olditem (remember, this is the original definition of \item that we stored)
    else
      end environment exami (\end{exami})
      begin environment exami (\begin{exami}) with parameters
          that will start at 10 (start = 10); and
          that will only be as wide as "10." (widest = {10.})
        \olditem (the original definition of \item that we stored)
        Immediately reset \item to what it was before (completely destroying this new 
          redefinition since it is no longer needed)
    end if
  else
    \olditem (the original definition of \item that we stored)
  end if

examii请注意,即使我们在环境中,我们也会检查是否正在使用枚举计数器exami。这是因为exami是一个常规的enumerate类似环境(因为\newlist{exami}{enumerate}{1}),并且enumerate类似环境<list>会自动分配一个名为的 1 级计数器<list>i;一个名为的 2 级计数器<list>ii;... 带有小写罗马后缀表示级别计数器。

相关内容