来自枚举/逐项列举的随机项目

来自枚举/逐项列举的随机项目

如果我有一个包含 5 个项目的 itemize 环境,并且我希望获得以下效果:

每次我编译时,都会以随机顺序列出 3 个随机不重复的项目。

说我的物品

  • A
  • C

经过一次编译后,输出可能如下所示:

  • A

我的问题与……密切相关,但又不同这个. 它的一个应用是从给定的一组问题中出卷。

有人知道使用乳胶是否可行吗?谢谢!

答案1

新的”LaTeX3编码界面非常适合解决此类问题。使用它,您可以使用命令拆分列表环境的内容\item以创建序列,然后可以使用\seq_shuffle:N命令随机打乱序列,然后允许您以随机顺序打印列表项。代码很短,一旦您熟悉了 LaTeX 3,就很容易理解。

为了实现这些想法,下面的代码定义了一个randonlist采用可选参数的环境,该参数指定要打印的项目数——默认情况下,所有列表项都会出现,但顺序是随机的。然后,以下代码回答了 OP 中的问题:

Three random items
\begin{randomlist}[3]
  \item A
  \item B
  \item C
  \item D
  \item E
\end{randomlist}

这是我第一次运行代码时生成的示例输出(每次编译文件时输出都会发生变化):

在此处输入图片描述

如果省略可选参数,则整个列表将被打乱:

在此处输入图片描述

以下是代码:

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\seq_new:N \l_randomlist_seq
\int_new:N \l_random_items_int
\NewDocumentEnvironment{randomlist}{ o  +b }
{
    % use a regular expression to split the environment
    % around the \item commands
    \regex_split:nnN { \s*\c{item}\s* } { #2 } \l_randomlist_seq
    \seq_pop_left:NN \l_randomlist_seq \l_items_tl % pop empty first item
    \seq_if_empty:NF \l_randomlist_seq {
        \seq_shuffle:N \l_randomlist_seq %% randonly shuffle items
        % the number of items to print is given by the optional #1
        % defaulting to the full list of items
        \IfNoValueTF{#1}{
            \int_set:Nn \l_random_items_int { \seq_count:N \l_randomlist_seq}
        }{
            \int_set:Nn \l_random_items_int { #1 }
        }
        % finally, insert the itemize environment
        \begin{itemize}
          \int_do_while:nNnn \l_random_items_int > 0 {
            \seq_pop:NN \l_randomlist_seq \l_tmpa_tl
            \item \tl_use:N \l_tmpa_tl
            \int_decr:N \l_random_items_int% one less item to go
          }
        \end{itemize}
    }
}{}
\ExplSyntaxOff


\begin{document}

  Five random items
  \begin{randomlist}
    \item A
    \item B
    \item C
    \item D
    \item E
  \end{randomlist}

  Three random items
  \begin{randomlist}[3]
    \item A
    \item B
    \item C
    \item D
    \item E
  \end{randomlist}


  Two random items
  \begin{randomlist}[2]
    \item A
    \item B
    \item C
    \item D
    \item E
  \end{randomlist}

\end{document}

就我个人而言,我会enumerate为此使用一个环境,但我已经使用了itemizeOP 中的环境。

答案2

您可以使用expl3。通过b参数类型,整个环境的内容都会被吸收。

我们可以将其拆分\item(丢弃如此获得的序列中的第一个空项)。然后我们打乱序列并仅输出前三个项,或者输出可选参数中指定的数量。如果我们请求的项目多于可用项目,则没有问题。

\seq_indexed_map_inline:Nn函数在这方面非常方便:它生成一个整数##1和相应的项目##2,因此我们可以测试索引是否大于所需项目的数量或序列的长度。

这个想法是类似于 Andrew 的,但实现方式表现出不同的特点,并且更为简单。

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentEnvironment{randomlist}{ O{3} +b }
 {
  \seq_set_split:Nnn \l__zuriel_randomlist_seq { \item } { #2 }
  \seq_pop_left:NN \l__zuriel_randomlist_seq \l_tmpa_tl
  \seq_shuffle:N \l__zuriel_randomlist_seq
  \begin{itemize}
  \seq_indexed_map_inline:Nn \l__zuriel_randomlist_seq
   {
    \int_compare:nTF { ##1 > \int_min:nn { #1 } { \seq_count:N \l__zuriel_randomlist_seq } }
     {
      \seq_map_break:
     }
     {
      \item ##2
     }
   }
  \end{itemize}
 }{}

\seq_new:N \l__zuriel_randomlist_seq

\ExplSyntaxOff

\begin{document}

This prints three items (default)
\begin{randomlist}
  \item A
  \item B
  \item C
  \item D
  \item E
\end{randomlist}

This prints two items
\begin{randomlist}[2]
  \item A
  \item B
  \item C
  \item D
  \item E
\end{randomlist}

This prints five items
\begin{randomlist}[5]
  \item A
  \item B
  \item C
  \item D
  \item E
\end{randomlist}

This prints five items as well
\begin{randomlist}[10]
  \item A
  \item B
  \item C
  \item D
  \item E
\end{randomlist}

\end{document}

在此处输入图片描述

相关内容