重新排列环境元素

重新排列环境元素

我想创建一组条目,其确切布局将由环境决定。即

\begin{Animals}
\Animal{Rat}{Mammals}
\Animal{Turtle}{Reptilia}
\Animal{Anaconda}{Reptilia}
\Animal{Whale}{Mammals}
\end{Animals}

根据“动物”环境的定义,可以扩展为

Animal   | Class
-------------------
Rat      | Mammals
Turtle   | Reptilia
Anaconda | Reptilia
Whale    | Mammals

或者

Mammals
  * Rat
  * Whale
Reptilia
  * Anaconda
  * Turtle

虽然创建第一种类型的环境似乎相对简单,但第二种环境对我来说似乎很神秘。任何建议或一些文档/资料/书籍的指导都非常感谢。或者也许我为这项任务(布局数据条目)选择了错误的工具,而它根本不应该用环境来完成。

提前致谢!

答案1

它对每种动物类别使用单独的列表,例如哺乳动物、鸟类、鱼类等,并使用存储所有类别的全局列表\Animal

\DisplayAnimals宏循环遍历各个类别并调用本地宏来显示该类别的单个动物,但未分类。

\documentclass{article}

\usepackage{xparse}

\ExplSyntaxOn


\seq_new:N \g_oytis_allcategories_seq


\NewDocumentCommand{\Animal}{+mm}{%
  \seq_if_exist:cF {g_oytis_#2_seq} {%
    \seq_new:c {g_oytis_#2_seq}
    \seq_gput_right:Nn \g_oytis_allcategories_seq {#2}
  }
  \seq_gput_right:cn {g_oytis_#2_seq}{#1}
  \seq_remove_duplicates:c {g_oytis_#2_seq}
}




\NewDocumentCommand{\DisplayAnimalCategory}{m}{%
  \seq_if_empty:cF {g_oytis_#1_seq} {
    \begin{tabular}{ll}
      #1 & \tabularnewline
      \seq_map_inline:cn {g_oytis_#1_seq} { & ##1 \tabularnewline}
    \end{tabular}
  }
}

\NewDocumentCommand{\DisplayAnimals}{}{%
  \seq_map_inline:Nn \g_oytis_allcategories_seq {
    \DisplayAnimalCategory{##1}
    \par
  }
}

\ExplSyntaxOff  

\begin{document}

\Animal{cat}{Mammals}

\Animal{dog}{Mammals}

\Animal{snake}{Reptilia}


\Animal{cow}{Mammals}

\Animal{tuna}{Fish}

\DisplayAnimals

\end{document}

在此处输入图片描述

答案2

以下是使用列表的方法电子工具箱包。这个想法是将\Animal数据添加到几个内部列表中——一个用于动物列表,一个用于类别列表,一个用于给定类别中的动物。为了打印动物/类别,我们使用 循环遍历这些列表\dolistloop

本着问题的精神,我将所有内容都包装在一个Animals带有可选参数的环境中。如果没有可选参数,则会打印动物和类别表。如果任何事物作为可选参数给出,则类别列表将作为description环境打印。您可以将其收紧,以便更严格地指定可选参数。

实际上,没有必要使用环境Animals,相反,\Animal命令可以在任何地方给出\PrintAnimalTable,然后\PrintAnimalsByCategory可以用来打印数据。另一方面,正如下面的 MWE 所示,这种方法的一个“特点”是命令\Animal对于环境来说是“本地的” Animals,因此不同的Animals环境可以在文档中彼此独立地使用。(\Animal在环境(任何环境)之外使用的命令将是“全局的”。)

下面的MWE的输出是:

在此处输入图片描述

代码如下:

\documentclass{article}
\usepackage{etoolbox}
\usepackage{environ}
\usepackage{booktabs}

\newcommand\animals{}
\newcommand\categories{}
\newcommand\Animal[2]{%
  % list of animals 
  \ifinlist{#1}\animals{}{\listadd\animals{#1&#2}}%
  % list of categories
  \ifinlist{#2}{\categories}{}{\listadd\categories{#2}}%
  % list of animals in category
  \ifinlistcs{#1}{cat-#2}{}{\listcsadd{cat-#2}{#1}}%
}
\newcommand\PrintAnimalsByCategory{%
   \renewcommand*\do[1]{\item[##1]% define \do to print itemized list
     \begin{itemize}
       \item[]
       \forlistcsloop{\item}{cat-##1}
     \end{itemize}
   }%
   \begin{description}
     \dolistloop{\categories}
   \end{description}%
}
\newcommand\PrintAnimalTable{%
   \renewcommand*\do[1]{##1\\}% define do to print line in tabular
   \begin{tabular}{ll}\toprule
     Animal & Category\\ \midrule
     \dolistloop{\animals}
     \bottomrule
    \end{tabular}%
}
\NewEnviron{Animals}[1][]
{\BODY% environment assumed to just contain \Animal commands,
  % so we process these
  \if\relax\detokenize{#1}\relax% print table by default
    \PrintAnimalTable%
  \else%
    \PrintAnimalsByCategory%
  \fi%
}

\begin{document}

  \begin{Animals}
    \Animal{Rat}{Mammals}
    \Animal{Turtle}{Reptilia}
    \Animal{Anaconda}{Reptilia}
    \Animal{Whale}{Mammals}
    \Animal{Albatross}{Bird}
  \end{Animals}

  \begin{Animals}[categories]
    \Animal{Rat}{Mammals}
    \Animal{Turtle}{Reptilia}
    \Animal{Anaconda}{Reptilia}
    \Animal{Whale}{Mammals}
  \end{Animals}

\end{document}

编辑

以下是上述代码的翻译解释3附加功能是列表现在按字母顺序排序(我不知道如何在没有 的情况下对列表进行排序expl3)。以下是新的输出:

在此处输入图片描述

新代码如下:

\documentclass{article}
\usepackage{expl3}
\usepackage{environ}
\usepackage{booktabs}

\newcommand\animals{}
\newcommand\categories{}

\ExplSyntaxOn
\seq_new:N \l_animals_seq    % list of animals
\seq_new:N \l_categories_seq % list of categories
\newcommand\Animal[2]{%
  % list of animals
  \seq_if_in:NnF \l_animals_seq {#1} { \seq_put_right:Nn \l_animals_seq {#1&#2}}
  % list of categories
  \seq_if_in:NnF \l_categories_seq {#2} { \seq_put_right:Nn \l_categories_seq {#2}}
  % list of animals in category
  \seq_if_exist:cTF {l_category_#2_seq}
    {  \seq_if_in:cnF {l_category_#2_seq} {#1}
                      { \seq_put_right:cn {l_category_#2_seq} {#1}}
    }{ \seq_new:c {l_category_#2_seq}
       \seq_put_right:cn {l_category_#2_seq} {#1}
    }
}
\cs_new_protected:Npn \l_sort_sequence:N #1 {
  \seq_sort:Nn #1 {
    \int_compare:nTF { \pdftex_strcmp:D { ##1 } { ##2 } < 0 }
                     {\sort_return_same:}
                     {\sort_return_swapped:}
   }
}
\cs_generate_variant:Nn \l_sort_sequence:N { c }

\newcommand\PrintAnimalsByCategory{%
   \begin{description}
     \l_sort_sequence:N \l_categories_seq
     \seq_map_inline:Nn \l_categories_seq {
       \item[##1]% print itemized list
       \begin{itemize}
         \item[]\item
         \l_sort_sequence:c {l_category_##1_seq}
         \seq_use:cn {l_category_##1_seq} {\item}
       \end{itemize}
     }
   \end{description}%
}
\newcommand\PrintAnimalTable{%
   \begin{tabular}{ll}\toprule
     Animal & Category\\ \midrule
     \l_sort_sequence:N \l_animals_seq
     \seq_use:Nn \l_animals_seq { \\}
     \\\bottomrule
    \end{tabular}%
}
\ExplSyntaxOff

\NewEnviron{Animals}[1][]
{\BODY% environment assumed to just contain \Animal commands,
  % so we process these
  \if\relax\detokenize{#1}\relax% print table by default
    \PrintAnimalTable%
  \else%
    \PrintAnimalsByCategory%
  \fi%
}

\begin{document}

  \begin{Animals}
    \Animal{Rat}{Mammals}
    \Animal{Turtle}{Reptilia}
    \Animal{Anaconda}{Reptilia}
    \Animal{Whale}{Mammals}
    \Animal{Albatross}{Bird}
  \end{Animals}

  \begin{Animals}[categories]
    \Animal{Rat}{Mammals}
    \Animal{Turtle}{Reptilia}
    \Animal{Anaconda}{Reptilia}
    \Animal{Whale}{Mammals}
  \end{Animals}

\end{document}

答案3

仅使用 TeX 基元的解决方案:

\def\sdef#1{\expandafter\def\csname#1\endcsname}
\long\def\addto#1#2{\expandafter\def\expandafter#1\expandafter{#1#2}}

\def\listca{} \def\listan{}
\def\Animal#1#2{\expandafter\ifx\csname ca:#2\endcsname\relax
   \sdef{ca:#2}{#1,}\addto\listca{#2,}%
   \else \expandafter\addto\csname ca:#2\endcsname{#1,}%
   \fi
   \addto\listan{#1:#2,}%
}
\def\taban #1:#2,{\ifx:#1:\else \firstfi #1:#2,\fi}
\def\firstfi#1:#2,\fi{\fi #1&#2\cr\taban}

\def\tabrule{\noalign{\medskip\hrule\medskip}}
\def\printanimals{\halign{\ ##\unskip\hfil&\quad##\unskip\hfil\ \cr \tabrule
   Animal & Category \cr \tabrule
   \expandafter \taban \listan:,\crcr \tabrule}
}
\def\printca#1,{\ifx,#1,\else 
   \par\noindent{\bf #1}\par
   \expandafter\expandafter\expandafter\printcaB\csname ca:#1\endcsname,%
   \expandafter\printca\fi
}
\def\printcaB#1,{\ifx,#1,\else\par\indent\llap{$\bullet$ }#1\par
   \expandafter\printcaB\fi
}
\def\printcategories{\expandafter\printca\listca,}

\Animal{Albatross}{Bird}
\Animal{Anaconda}{Reptilia}
\Animal{Rat}{Mammals}
\Animal{Turtle}{Reptilia}
\Animal{Whale}{Mammals}

\printanimals

\bigskip
\printcategories

\end

相关内容