我正在尝试使用 datatools\DTLfetch
从 .csv 文件加载的数据库中获取一个实数,然后将这个数字参数传递给\FPeval
。
问题是它\DTLfetch
似乎总是返回一个字符串而不是数字,这会导致错误,因为 FP 无法处理字符串数据类型。
\DTLgetvalue
总是返回所需的数字数据类型并且一切正常,但是,我确实需要\DTLfetch
。
过去两天我一直在尝试弄清楚如何在 LaTeX 中将字符串转换为数字数据类型,或者如何返回\DTLfetch
数字值而不是字符串。
LaTeX 在这方面的能力是否严重不足?还是我遗漏了某些基本的东西?我应该使用 Sagetex 进行转换吗?
非常感谢!
答案1
TeX 是一种宏语言,除了字符串之外没有其他类型。(有类型寄存器,但与此无关)问题不在于\DTLfetch
“返回”字符串,而在于它\DTLfetch
不可扩展。
不可扩展的宏例如\DTLfetch
不会扩展为值,但有时它们会在当前列表中插入一些结果。这就是为什么您可以在文档中使用查看结果DTLfetch
,但在内部不起作用的原因\FPeval
。
为了解决这个问题,你可以使用egreg 编写的\DTLfetchsave
变体\DTLfetch
检索 `\DTLfetch` 的子字符串它将结果保存在一个新的宏中,然后可以将其扩展(类似于\FPeval
其自身):
\begin{filecontents*}{students.csv}
name,grade
Joe Bloggs,2.7
Jane Doe,1.0
John Smith,3.0
\end{filecontents*}
\documentclass{article}
\usepackage{datatool,fp}
% From egreg at https://tex.stackexchange.com/questions/335483/retrieving-substring-of-dtlfetch
\newcommand{\DTLfetchsave}[5]{%
\edtlgetrowforvalue{#2}{\dtlcolumnindex{#2}{#3}}{#4}%
\dtlgetentryfromcurrentrow{\dtlcurrentvalue}{\dtlcolumnindex{#2}{#5}}%
\let#1\dtlcurrentvalue
}
\begin{document}
\DTLloaddb{students}{students.csv}
\DTLfetchsave\grade{students}{name}{Jane Doe}{grade}
\FPeval\doublegrade{2*\grade}
\doublegrade
\end{document}
答案2
当我尝试使用 (CSV) 数据库中的数据通过 TikZ/PGFPlots 绘制单个值或使用 siunitx 打印值时,我遇到了同样的问题。
和这在发布后我发现了如何将数据库中的所有值存储为以相应键命名的(扩展的)LaTeX 变量:
\documentclass[tikz]{standalone}
\usepackage{siunitx}
\usepackage{filecontents}
\begin{filecontents*}{mydb.csv}
key;value
mykey;1.0
\end{filecontents*}
% Relevant code below
\usepackage{datatool}
\DTLsetseparator{;}
\DTLloaddb{mydb}{mydb.csv}
\begin{document}
\DTLforeach{mydb}{\Key=key,\Value=value}
{%
\cslet{\Key}{\Value}%
}
\DTLfetch{mydb}{key}{mykey}{value} works\\
% while $\num{\DTLfetch{mydb}{key}{mykey}{value}}$ fails
\mykey prints the value for mykey, $\num{\mykey}$ also works
\end{document}
但是,加载具有相似键的多个数据库会重新分配相同的变量。
作为一个快速修复,我将DTLFetch
值分配给以数据库名称和键的连接命名的变量,并编写了一个函数来解析后者:
\documentclass[tikz]{standalone}
\usepackage{siunitx}
\usepackage{filecontents}
\begin{filecontents*}{mydb.csv}
key;value
mykey;1.0
\end{filecontents*}
% Relevant code below
\usepackage{datatool}
\DTLsetseparator{;}
\DTLloaddb{mydb}{mydb.csv}
\newcommand{\getval}[2]{\csname#1#2\endcsname}
\begin{document}
\DTLforeach{mydb}{\Key=key,\Value=value}
{%
\cslet{mydb\Key}{\Value}%
}
\getval{mydb}{mykey} prints the value for mykey, $\num{\getval{mydb}{mykey}}$ also works
\end{document}
答案3
我还发现,
\xDTLassignfirstmatch
它datatool
的工作原理似乎与相同\DTLfetch
,但具有扩展,并且对我来说效果很好!