我想创建一组条目,其确切布局将由环境决定。即
\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}}%
% 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}}
% 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\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