TransWikia.com

How to convert datatypes?

TeX - LaTeX Asked by alex dinovitser on September 28, 2021

I am trying to use datatools DTLfetch to grab a real number from a database loaded from a .csv file, and then pass this numeric argument to FPeval.

Problem is that DTLfetch always seems to return a string instead of a numeric, which gives an error because FP can’t handle string datatypes.

DTLgetvalue always returns the desired numeric datatype and everything works, however, I really need DTLfetch.

I have spent the last two days trying to figure out how to convert a string to a numeric datatype in LaTeX, or alternatively, how to get DTLfetch to return a numeric value instead of a string.

Is LaTeX seriously deficient in this capability? or am I missing something fundamental? Should I use Sagetex to do the conversion?

Many thanks!

3 Answers

TeX is a macro language, it does not have any other types than strings. (There are typed registers, but they are not relevant here) The problem is not that DTLfetch "returns" a string, it is that DTLfetch is not expandable.

Non-expandable macros like DTLfetch do not expand to a value, but sometimes they insert some results in the current list. That is why you can use see the result from DTLfetch in your document, but it does not work inside FPeval.

To fix this, you can use a variant DTLfetchsave of DTLfetch which egreg has written for retrieving substring of `DTLfetch`. It saves the result in a new macro, which can then be expanded (similar to FPeval itself):

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#1dtlcurrentvalue
}

begin{document}
  DTLloaddb{students}{students.csv}
  DTLfetchsavegrade{students}{name}{Jane Doe}{grade}
  FPevaldoublegrade{2*grade}
  doublegrade
end{document}

Answered by Marcel Krüger on September 28, 2021

I also discovered xDTLassignfirstmatch in datatool that seems to work the same as DTLfetch, with expansion, and works great for me!

Answered by alex dinovitser on September 28, 2021

I had the same issue when trying to use data from a (CSV) database for plotting single values with TikZ/PGFPlots or for printing values using siunitx.

With this post I found out how to store all values from the database as (expanded) LaTeX variable named after the respective key:

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}

However, loading multiple databases with similar keys would re-assign the same variables.

As a quick fix, I made DTLFetch assign the values to variables named after a concatenation of database name and key and wrote a function to parse the latter:

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#2endcsname}

begin{document}
DTLforeach{mydb}{Key=key,Value=value}
{%
   cslet{mydbKey}{Value}%
}
getval{mydb}{mykey} prints the value for mykey, $num{getval{mydb}{mykey}}$ also works
end{document}

Answered by F1iX on September 28, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP