如何获取 datatool 数据库中特定列的所有不同值以及另一列中的对应值?在下面的示例中,我想要获取输出:
数据库中 Xland 的城市是 Xcity
数据库中 Yland 的城市是 Ycity
数据库中 Zland 的城市是 Zcity
我知道我可以获取如下例所示的唯一城市列表(类似地,唯一国家列表)但我该如何将它们结合起来?
\documentclass{article}
\usepackage{etoolbox}
\usepackage{datatool}
\begin{filecontents}{test.csv}
Name,Town,Country,Age
Adam,Xcity,Xland,20
Berta,Ytown,Yland,30
Cesar,Ztington,Zland,40
Dora,Ztington,Zland,20
Emil,Ytown,Yland,30
Franz,Ytown,Yland,20
\end{filecontents}
\DTLloaddb{data}{test.csv}
\begin{document}
\newcommand*{\uniquetowns}{}
\newcommand*{\uniquecountries}{}
\DTLforeach*{data}{\Town=Town,\uniquecountries=Country}{%
\expandafter\DTLifinlist\expandafter{\Town}{\uniquetowns}%
{}% do nothing, already in list
{% add to list
\ifdefempty{\uniquetowns}%
{\let\uniquetowns\Town}% first element of list
{% append to list
\eappto\uniquetowns{,\Town}%
}%
}%
}
List of unique towns: \uniquetowns.
\end{document}
相关问题:获取数据工具数据库中特定列的所有不同值
答案1
我可能不太明白你想要实现什么,但是这样怎么样?
\documentclass{article}
\usepackage{datatool}
\begin{filecontents}{test.csv}
Name,Town,Country,Age
Adam,Xcity,Xland,20
Berta,Ytown,Yland,30
Cesar,Ztington,Zland,40
Dora,Ztington,Zland,20
Emil,Ytown,Yland,30
Franz,Ytown,Yland,20
\end{filecontents}
\DTLloaddb{data}{test.csv}
\begin{document}
\newcommand*{\uniquetowns}{}
% \newcommand*{\uniquecountries}{}
\DTLforeach*{data}{\Town=Town, \Country=Country}{%
\expandafter\DTLifinlist\expandafter{\Town}{\uniquetowns}%
{}% do nothing, already in list
{% add to list
\ifdefempty{\uniquetowns}%
{\let\uniquetowns\Town}% first element of list
{% append to list
\eappto\uniquetowns{,\Town}%
}%
A city of \Country{} in the database is \Town .
}%
}
\end{document}
这将针对每个不同的城镇输出:
但是,在您的示例中,城镇和国家的名称是这样选择的:每个城镇只能位于特定国家,每个国家只能与一个特定城镇相关。您是否需要处理两个同名城镇可能位于不同国家的情况?
如果是这种情况,您可以将每个条目的国家和城镇名称合并起来,以创建唯一的国家城镇条目。这样,您就可以保证获得每个国家的每个城镇。(请注意,我不得不更改一些宏才能处理组合字符串。)
\documentclass{article}
\usepackage{datatool}
\begin{filecontents}{test.csv}
Name,Town,Country,Age
Adam,Rome,Italy,20
Berta,Rome,U.S.,30
Cesar,Berlin,Germany,40
Dora,Munich,Germany,20
Emil,New York,U.S.,30
Franz,Milan,Italy,20
Gustav,Milan,Italy,20
Heinrich,Rome,Italy,20
\end{filecontents}
\DTLloaddb{data}{test.csv}
\begin{document}
\newcommand*{\uniquetowns}{}
%\newcommand*{\uniquecountries}{}
\noindent%
\DTLforeach*{data}{\Town=Town, \Country=Country}{%
\DTLifSubString{\uniquetowns}{\Town.\Country}%
{}% do nothing, already in list
{% add to list
\ifdefempty{\uniquetowns}%
{% first element of list
\eappto\uniquetowns{\Town.\Country}%
}%
{% append to list
\eappto\uniquetowns{,\Town.\Country}%
}%
A city of \Country{} in the database is \Town . \\
}%
}
\end{document}
输出为:
如您所见,意大利和美国的罗马都在考虑之列,德国的慕尼黑和柏林也在考虑之列。不过,这份名单还是很独特的,因为罗马(意大利)和米兰(意大利)都只上榜一次。
更新
由于原帖作者表示他们想要一个结果,即所有属于一个国家的城镇都合并在一个句子中,所以我又试了一次。但是,要做到这一点,\DTLforeach
需要多个实例。因此,如果有大量数据需要继续,则需要一些时间。
\documentclass{article}
\usepackage{datatool}
\begin{filecontents}{test.csv}
Name,Town,Country,Age
Adam,Rome,Italy,20
Berta,Rome,U.S.,30
Cesar,Berlin,Germany,40
Dora,Munich,Germany,20
Emil,New York,U.S.,30
Franz,Milan,Italy,20
Gustav,Milan,Italy,20
Heinrich,Rome,Italy,20
\end{filecontents}
\DTLloaddb{data}{test.csv}
\DTLnewdb{countries}
\newcommand*{\uniquecountries}{}
\newcommand*{\uniquetowns}{}
\newcommand*{\countrysentence}{}
\begin{document}
% first, generate database with unique entries
\DTLforeach*{data}{\Country=Country}{%
\DTLifSubString{\uniquecountries}{\Country}%
{% do nothing, already in list
}%
{% add to list
\DTLnewrow{countries}%
{\dtlexpandnewvalue\DTLnewdbentry{countries}{Country}{\Country}}%
\eappto\uniquecountries{\Country : }%
}%
}%
\noindent%
\DTLforeach*{countries}{\CurrentCountry=Country}{%
\renewcommand{\uniquetowns}{}%
\renewcommand{\countrysentence}{}%
\DTLforeach*[\DTLiseq{\CurrentCountry}{\Country}]{data}%
{\Country=Country, \Town=Town}{%
\DTLifSubString{\uniquetowns}{\Town}%
{% do nothing, already in list
}%
{% add to list
\eappto\uniquetowns{\Town : }%
\ifdefempty{\countrysentence}%
{% first element of list
\eappto\countrysentence{The cities in \CurrentCountry{} are \Town}%
}%
{% append to list
\eappto\countrysentence{, \Town}%
}%
}%
}%
\eappto\countrysentence{.}%
\countrysentence \\
}
\end{document}
输出:
也许这可以更轻松地实现,但我找不到任何更简单的解决方案。有两个问题导致了这种特定的设置:首先,除了通过另一个存储列表的宏之外,没有其他方法可以仅过滤唯一数据;其次,据我所知,您无法轻松读取存储在宏中的数据\DTLforeach
。因此,我需要创建一个存储在宏中的列表以及一个数据库,这似乎有点麻烦。但也许我错了。