![Datatool:如何按特定顺序手动选择一些行](https://linux22.com/image/252486/Datatool%EF%BC%9A%E5%A6%82%E4%BD%95%E6%8C%89%E7%89%B9%E5%AE%9A%E9%A1%BA%E5%BA%8F%E6%89%8B%E5%8A%A8%E9%80%89%E6%8B%A9%E4%B8%80%E4%BA%9B%E8%A1%8C.png)
我有一个大型的多用途数据库,我想从中选择几个项目(使用标签)并按给定的顺序打印它们,而不是数据库顺序或任何与条目相关的顺序。
例如,我目前使用这个代码(在这个网站上找到,感谢 Peter Grill):
\documentclass{article}
\usepackage{datatool}
\usepackage{longdata}
\usepackage{filecontents}
\begin{filecontents*}{foo.dat}
Hammer001, Hammer, 1 , 0 , 1 , 10 , 1 , light\\
Hammer002, Hammer, 2 , 0 , 1 , 10 , 1 , heavy\\
Hammer003, Hammer, 3 , 0 , 1 , 10 , 1 , really heavy\\
Longsword001,Longsword, 1 , -1 , 2 , 75 , 2 , one-handed \\
Longsword002,Longsword, 2 , -1 , 2 , 75 , 2 , two-handed \\
Longsword003,Longsword, 3 , -1 , 2 , 75 , 2 , three-handed \\
\end{filecontents*}
\newcommand{\PrintDTLTable}[2]{%
% #1 = database to search
% #2 = list of rowIDs
\begin{enumerate}
\DTLforeach*[\DTLisSubString{#2}{\RowID}]{#1}{%
\RowID=RowID,%
\Label=Label,%
\Cost=Cost,%
\Weight=Weight,%
\Description=Description%
}{%
\item \Label ; Price=\Cost ; Weight=\Weight ; It's very \Description
}%
\end{enumerate}
}%
\begin{document}
\DTLloaddb[noheader,keys={RowID,Label,Cost,Weight,PropA,PropB,PropC,Description}]{myDB}{foo.dat}
\PrintDTLTable{myDB}{Hammer001,Hammer003,Longsword003}
\end{document}
命令
\PrintDTLTable{myDB}{Hammer001,Hammer003,Longsword003}
做的正是我想要的,除了
\PrintDTLTable{myDB}{Hammer003,Longsword003,Hammer001}
显然会产生完全相同的结果。
有什么办法可以保持给定的顺序?(抱歉我的英语不好)
答案1
\DTLforeach
逐行访问行。因此,数据库的行顺序很重要:
\DTLforeach*[\DTLisSubString{#2}{\RowID}]{#1}{%
% #2 = list of rowIDs
在以下解决方案中,我将数据提取放在一个 for 循环中,该循环遍历给定的行 ID。有许多 for 循环,例如 LaTeX 的循环\@for
。我使用的\comma@parse
是来自包 kvsetkeys 的循环,因为它会从列表中的条目中删除前导和尾随空格。然后将行 ID 与行 ID 进行比较\equal
以仅获得精确匹配。
\usepackage{kvsetkeys}
\makeatletter
\newcommand{\PrintDTLTable}[2]{%
% #1 = database to search
% #2 = list of rowIDs
\begin{enumerate}
\comma@parse{#2}{%
\DTLforeach*[\equal{\comma@entry}{\RowID}]{#1}{%
\RowID=RowID,%
\Label=Label,%
\Cost=Cost,%
\Weight=Weight,%
\Description=Description%
}{%
\item \Label ; Price=\Cost ; Weight=\Weight ; It's very \Description
\dtlbreak
}%
\@gobble % ignore the entry argument provided by \comma@parse
}%
\end{enumerate}
}%
\makeatother
当然,该算法的运行时间表现不佳。对于具有 n 个条目和 m 个选定行的数据库,其时间为 O(n*m)。这意味着如果输出整个数据库,则时间为 O(n²)。理论上,排序可以在 O(n*log(n)) 中完成。