我使用 datatool 解析 CSV 文件。我想使用 makro \DTLminforcolumn 来计算列的最小值。如果每行都有一个值,则此方法有效,但如果有空行,则效果不佳。我如何告诉 datatool 忽略空行?
梅威瑟:
\documentclass{article}
\usepackage{filecontents}
\usepackage{datatool}
\begin{filecontents*}{example1.csv}
title;value
test1;1
test2;
test3;3
test4;2
\end{filecontents*}
\begin{filecontents*}{example2.csv}
title;value
test1;1
test2;2
test3;3
test4;4
\end{filecontents*}
\begin{document}
\DTLsetseparator{;}%
\DTLloaddb{a}{example1.csv}
\DTLminforcolumn{a}{value}{\minValueFirstExample}
\DTLsetseparator{;}%
\DTLloaddb{b}{example2.csv}
\DTLminforcolumn{b}{value}{\minValueSecondExample}
Min Value1: \minValueFirstExample\\ %Should be 1 and not 2
Min Value2: \minValueSecondExample %Is correct
\end{document}
答案1
加载包后添加以下几行datatool
。
\usepackage{xpatch}
\patchcmd\DTLminforcolumn{%
\DTLmin{#3}{#3}{\DTLthisval}%
}{%
\ifdefempty\DTLthisval{}{\DTLmin{#3}{#3}{\DTLthisval}}%
}{}{}
\documentclass{article}
\usepackage{datatool}
\usepackage{xpatch}
\patchcmd\DTLminforcolumn{%
\DTLmin{#3}{#3}{\DTLthisval}%
}{%
\ifdefempty\DTLthisval{}{\DTLmin{#3}{#3}{\DTLthisval}}%
}{}{}
\begin{document}
\DTLlistskipemptytrue
\DTLsetseparator{;}%
\DTLloaddb{a}{example1.csv}
\DTLminforcolumn{a}{value}{\minValueFirstExample}
\DTLsetseparator{;}%
\DTLloaddb{b}{example2.csv}
\DTLminforcolumn{b}{value}{\minValueSecondExample}
\noindent
Min Value1: \minValueFirstExample\\ %Should be 1 and not 2
Min Value2: \minValueSecondExample %Is correct
\end{document}
解释。 \DTLminforcolumn
定义datatool.sty
如下:
\newcommand*{\DTLminforcolumn}[3]{% #1 database, #2 col name, #3 return value
\def#3{}% #3 := ""
\DTLifdbexists{#1}{% if database #1 exists:
\@sDTLifhaskey{#1}{#2}{% if column #2 exists in db #1:
\@sdtlforcolumn{\DTLthisval}{#1}{#2}{% for DTLthisval in column #2:
\ifdefempty{#3}{% if #3 == "":
\let#3\DTLthisval% #3 := DTLthisval
}{% else:
\DTLmin{#3}{#3}{\DTLthisval}% #3 := min(#3,DTLthisval)
}%
}%
}{% else:
\PackageError{datatool}{Key `#2' % raise exception
doesn't exist in database `#1'}{}%
}%
}{% else:
\PackageError{datatool}{Data base % raise exception
`#1' doesn't exist}{}%
}%
}
\DTLmin
如果两个数字中任何一个为空,则返回“空”。因此,当\DTLthisval
恰好为空时(因为列中的字段为空),到目前为止计算出的最小值#3
将重置为“空”,就像循环开始之前一样。
为了改变这种行为,我们必须确保只计算非空字段的最小值。因此,我们使用\patchcmd
包中的xpatch
来替换\DTLminforcolumn
行中的
\DTLmin{#3}{#3}{\DTLthisval}% #3 := min(#3,DTLthisval)
经过
\ifdefempty\DTLthisval{% if DTLthisval == "":
}{% else:
\DTLmin{#3}{#3}{\DTLthisval}% #3 := min(#3,DTLthisval)
}%