我只想过滤给定数据库中的重复项并将其删除。在我的特定情况下,数据库是从外部.csv
数据加载的,并且只有一个列。但为了在这个 MWE 中保持简单,我只是创建了数据库floorRawData
并用一些数据填充它。
因为我没有找到任何现成的删除重复项的功能,所以我自己尝试了如下方法:
\documentclass{article}
\usepackage{datatool}
\begin{document}
\DTLnewdb{floorFilteredData}
\DTLnewdb{floorRawData}
\DTLnewrow{floorRawData}
\DTLnewdbentry{floorRawData}{FloorRaw}{groundFloor}
\DTLnewrow{floorRawData}
\DTLnewdbentry{floorRawData}{FloorRaw}{upperFloor}
\DTLnewrow{floorRawData}
\DTLnewdbentry{floorRawData}{FloorRaw}{groundFloor}
\DTLnewrow{floorRawData}
\DTLnewdbentry{floorRawData}{FloorRaw}{basementFloor}
\DTLdisplaydb{floorRawData}\\ % Result as expected!
\newcommand{\noDBentry}{FALSE}
\DTLforeach*{floorRawData}{\floorRaw=FloorRaw}
{
\noindent FloorRaw Element: \floorRaw\\
\DTLifdbempty{floorFilteredData}
{
\DTLnewrow{floorFilteredData}
\DTLnewdbentry{floorFilteredData}{FloorFiltered}{\floorRaw}
\\\DTLdisplaydb{floorFilteredData}\\[5mm]
}
{
\DTLforeach{floorFilteredData}{\floorFiltered=FloorFiltered}
{
FloorFiltered Element: \floorFiltered\\ % Why is this element "upperFloor" and not "groundFloor"?
\ifthenelse{\equal{\floorRaw}{\floorFiltered}}
{
\renewcommand{\noDBentry}{TRUE}
}{}
}
\ifthenelse{\equal{\noDBentry}{FALSE}}
{
Add new data: \floorFiltered % Never called!
\DTLnewrow{floorFilteredData}
\DTLnewdbentry{floorFilteredData}{FloorFiltered}{\floorRaw}
}
{
\renewcommand{\noDBentry}{FALSE}
}
}
}
\DTLdisplaydb{floorFilteredData}\\
\end{document}
在这个 MWE 中,我只是解析floorRawData
数据库并检查当前元素是否已经是我的floorFilteredData
数据库的一部分。如果它是一部分,那么我不会在floorFilteredData
数据库中添加新元素,否则我想添加这个元素。
所以最后我期望一个floorFilteredData
数据库,其中每一行都是不同的\floorFiltered
元素。
但正如您所见,\floorFiltered
元素似乎始终是相同的元素\floorRaw
。
因此我的预期是,这\DTLforeach{floorFilteredData}{\floorFiltered=FloorFiltered}
不会从头开始。
我看了一下 datatool 包手册第 58 页https://texdoc.org/serve/datatool/0但我没有从中得到正确的线索......
答案1
经过几个小时的搜索,我发现了这个很棒的常问问题来自 datatool 包维护者 Nicola LC Talbot :) 我想在包装手册在第43页。
\dtlexpandnewvalue
解决方案是在以编程方式添加 DB 元素之前进行添加。就是这样!
\documentclass{article}
\usepackage{datatool}
\begin{document}
\DTLnewdb{floorFilteredData}
\DTLnewdb{floorRawData}
\DTLnewrow{floorRawData}
\DTLnewdbentry{floorRawData}{FloorRaw}{groundFloor}
\DTLnewrow{floorRawData}
\DTLnewdbentry{floorRawData}{FloorRaw}{upperFloor}
\DTLnewrow{floorRawData}
\DTLnewdbentry{floorRawData}{FloorRaw}{groundFloor}
\DTLnewrow{floorRawData}
\DTLnewdbentry{floorRawData}{FloorRaw}{basementFloor}
\DTLdisplaydb{floorRawData}\\ % Result as expected!
\newcommand{\noDBentry}{FALSE}
\dtlexpandnewvalue % Just add this line
\DTLforeach*{floorRawData}{\floorRaw=FloorRaw}
{
\DTLifdbempty{floorFilteredData}
{
\DTLnewrow{floorFilteredData}
\DTLnewdbentry{floorFilteredData}{FloorFiltered}{\floorRaw}
}
{
\DTLforeach{floorFilteredData}{\floorFiltered=FloorFiltered}
{
\ifthenelse{\equal{\floorRaw}{\floorFiltered}}
{
\renewcommand{\noDBentry}{TRUE}
}{}
}
\ifthenelse{\equal{\noDBentry}{FALSE}}
{
\DTLnewrow{floorFilteredData}
\DTLnewdbentry{floorFilteredData}{FloorFiltered}{\floorRaw}
}
{
\renewcommand{\noDBentry}{FALSE}
}
}
}
\DTLdisplaydb{floorFilteredData}\\
\end{document}