在 LaTeX 中仅从列表中选择某些项目

发布于 2024-08-23 23:56:04 字数 548 浏览 4 评论 0原文

我有一个 LaTeX 文档,它基本上是一个大型枚举环境,包含数百个项目。我希望能够发出这样的命令

\printitems{2,5,12,45-48}

,该命令将仅输出请求的项目。

类似的命令 \onlyslidesslides.cls 的一部分,但我无法弄清楚那里发生了什么并使其适应我的需要。

我可以用环境列表替换 item 列表,例如

\begin{myitem}
...
\end{myitem}

\begin{myitem}
...
\end{myitem}

使用 \newcounter 等,如果它有助于实现我的目的 - 只能打印一些具有给定编号的项目,无需剪切和粘贴。如果需要,我可以将这些项目放在一个文件中,并将 \printitems 命令放在另一个文件中。

我无法将数字放入文件中 - 文件不断变化,我需要自动枚举。

I have a LaTeX document which is basically one big enumerate environment, with a few hundreds of items. I want to be able to issue a command like

\printitems{2,5,12,45-48}

which will output only the requested items.

A similar command \onlyslides is a part of slides.cls, but I cannot figure out what goes on there and adapt it to my needs.

I can replace the list of item's with a list of environments, like

\begin{myitem}
...
\end{myitem}

\begin{myitem}
...
\end{myitem}

with a \newcounter etc. if it helps to achieve my purpose — being able to print only some items with given numbers without cut-and-pasting. I can have the items in one file, and the \printitems command in another, if needed.

I can not put the numbers in the file — the file is constantly changing, and I need the automatic enumeration.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

╰つ倒转 2024-08-30 23:56:04

好吧,那么,我们开始吧。

如下所示,编码的主要部分是解析逗号分隔的范围输入。之后,很容易检查您在枚举环境(或其他环境)中达到的数字并有条件地显示该项目。

您可以从这里复制并粘贴到一个空的 .tex 文档中,它应该可以正常工作:


%% 首先,我使用 expl3 包来完成大部分编码。让一些事情变得更容易。

\documentclass{article}
\usepackage{expl3}
\ExplSyntaxOn

%% 这是循环逗号列表范围输入的函数,如 -2,4-6,8,10-:

\prg_new_conditional:Nnn \i_in_range:nn {TF,T,F} {
  \bool_set_false:N \l_tmpa_bool
  \clist_map_inline:nn {#2} {
    \parse_range:w ##1 - \q_marker - \q_nil #1 \q_nil
  }
  \bool_if:NTF \l_tmpa_bool \prg_return_true: \prg_return_false:
}

%% 以及返回输入参数是否包含在范围内的辅助函数:

\cs_set:Npn \parse_range:w #1 - #2 - #3 \q_nil #4 \q_nil {
  \tl_if_eq:nnTF {\q_marker}{#2}{
    \intexpr_compare:nT {#4=#1} {\bool_set_true:N \l_tmpa_bool}
  }{
    \tl_if_empty:nTF {#2}{
      \intexpr_compare:nT {#4>=#1} {\bool_set_true:N \l_tmpa_bool}
    }{
      \tl_if_empty:nTF {#1}{
        \intexpr_compare:nT {#4<=#2} {\bool_set_true:N \l_tmpa_bool}
      }{
        \intexpr_compare:nT {#4>=#1} {
          \intexpr_compare:nT {#4<=#2}
            {\bool_set_true:N \l_tmpa_bool}
        }
      }
    }
  }
}
\cs_generate_variant:Nn \i_in_range:nnTF {nV}

%% 这是输入列表中每个项目的命令:

\newcommand\numitem[1]{
  \i_in_range:nVTF {\value{enumi}+1}{\l_item_range_tl}{
    \item #1
  }{
    \stepcounter{enumi}
  }
}

%% 以及带有范围参数的枚举环境:

\newenvironment{someitems}[1]{
  \tl_set:Nn \l_item_range_tl {#1}
  \begin{enumerate}
}{
  \end{enumerate}
}
\ExplSyntaxOff

%% 最后,一个示例:

\begin{document}
\begin{someitems}{-2,4-6,8,10-}
\numitem{one}\numitem{two}\numitem{three}
\numitem{four}\numitem{five}\numitem{six}
\numitem{seven}\numitem{eight}\numitem{nine}
\numitem{ten}\numitem{eleven}
\end{someitems}
\end{document}

Alright, then, here we go.

As you can see below, the main part of the coding is parsing the comma separated range input. After that, it's easy to check what number you're up to in the enumerate environment (or whatever) and conditionally display the item.

You can copy and paste from here on into an empty .tex document and it should just work:


%% First of all, I'm using the expl3 package to do most of this coding. Makes some things easier.

\documentclass{article}
\usepackage{expl3}
\ExplSyntaxOn

%% Here's the function to loop over comma-list range input like -2,4-6,8,10-:

\prg_new_conditional:Nnn \i_in_range:nn {TF,T,F} {
  \bool_set_false:N \l_tmpa_bool
  \clist_map_inline:nn {#2} {
    \parse_range:w ##1 - \q_marker - \q_nil #1 \q_nil
  }
  \bool_if:NTF \l_tmpa_bool \prg_return_true: \prg_return_false:
}

%% And the auxiliary function to return whether the input argument is contained within the range:

\cs_set:Npn \parse_range:w #1 - #2 - #3 \q_nil #4 \q_nil {
  \tl_if_eq:nnTF {\q_marker}{#2}{
    \intexpr_compare:nT {#4=#1} {\bool_set_true:N \l_tmpa_bool}
  }{
    \tl_if_empty:nTF {#2}{
      \intexpr_compare:nT {#4>=#1} {\bool_set_true:N \l_tmpa_bool}
    }{
      \tl_if_empty:nTF {#1}{
        \intexpr_compare:nT {#4<=#2} {\bool_set_true:N \l_tmpa_bool}
      }{
        \intexpr_compare:nT {#4>=#1} {
          \intexpr_compare:nT {#4<=#2}
            {\bool_set_true:N \l_tmpa_bool}
        }
      }
    }
  }
}
\cs_generate_variant:Nn \i_in_range:nnTF {nV}

%% This is the command to input each item of your list:

\newcommand\numitem[1]{
  \i_in_range:nVTF {\value{enumi}+1}{\l_item_range_tl}{
    \item #1
  }{
    \stepcounter{enumi}
  }
}

%% And the enumerate environment with a range argument:

\newenvironment{someitems}[1]{
  \tl_set:Nn \l_item_range_tl {#1}
  \begin{enumerate}
}{
  \end{enumerate}
}
\ExplSyntaxOff

%% Finally, an example:

\begin{document}
\begin{someitems}{-2,4-6,8,10-}
\numitem{one}\numitem{two}\numitem{three}
\numitem{four}\numitem{five}\numitem{six}
\numitem{seven}\numitem{eight}\numitem{nine}
\numitem{ten}\numitem{eleven}
\end{someitems}
\end{document}
若相惜即相离 2024-08-30 23:56:04

这样做的困难(或者更确切地说,不平凡)的部分是解析逗号分隔的输入。有几个包已经实现了这个功能;也许 Lipsum 的实现足够简单,可以根据您的目的进行提取。

之后,只需在每次点击某个项目时步进计数器即可,并根据逗号列表的解析方式显示或不显示内容。

The difficult (or rather, non-trivial) part of doing this is parsing the comma-separated input. Several packages have implemented this; perhaps lipsum's implementation is simple enough to extract for your purposes.

After that, it's just a matter of stepping a counter every time you hit an item and either display the contents or not depending on how the comma-list is parsed.

樱&纷飞 2024-08-30 23:56:04

首先使用 foreach 函数分割

Split comma-separated parameters in LaTeX 中 给出的逗号分隔列表

您可以通过删除使用的常量参数 #2 来简化它。

然后按如下方式定义您的项目(这是在 TeX 中构建哈希的方法):

\@namedef{item_1}{This is item 1}
\@namedef{item_2}{This is item 2}
\@namedef{item_3}{This is item 3}

定义要在 foreach 中使用的函数:

\def\printSingleItem#1{%
    \@ifundefined{item_#1}{%
         \PackageWarning{MyPackage}{Undefined Item #1}%
    }{%
         \@nameuse{item_#1}% This can be more fancy here, using formatting etc.
    }%
}

最后定义 printitems

\def\printitems#1{\foreach{\printSingleItem}{#1}}

First use the foreach function to split a comma separated list given in

Split comma-separated parameters in LaTeX

You can simplify it by removing the constant parameter #2 used.

Then define your items as following (this is the way to build a hash in TeX):

\@namedef{item_1}{This is item 1}
\@namedef{item_2}{This is item 2}
\@namedef{item_3}{This is item 3}

Define a function to be used in foreach:

\def\printSingleItem#1{%
    \@ifundefined{item_#1}{%
         \PackageWarning{MyPackage}{Undefined Item #1}%
    }{%
         \@nameuse{item_#1}% This can be more fancy here, using formatting etc.
    }%
}

Last define printitems

\def\printitems#1{\foreach{\printSingleItem}{#1}}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文