如果未找到条目,datatool 的 \DTLfetch 将返回最后找到的值,而不是“未定义值”

如果未找到条目,datatool 的 \DTLfetch 将返回最后找到的值,而不是“未定义值”

如果提供的密钥不在数据库中,我想要设置一些条件来决定如何处理。但是,如果 \DTLfetch 之前找到过一个值,它会返回一个值。我如何才能捕获此示例中的所有“x”?

\documentclass{article}

\usepackage{datatool}

% csv file 1
\begin{filecontents*}{abbreviationss.csv}
    term, abbreviation
    Machine Learning, ML
    Artificial Neural Network, ANN
\end{filecontents*}

\DTLloaddb{abbreviations}{abbreviationss.csv}

\begin{document}

\begin{itemize}
    \item x : \DTLfetch{abbreviations}{term}{x}{abbreviation}
    \item Machine Learning : \DTLfetch{abbreviations}{term}{Machine Learning}{abbreviation}
    \item x : \DTLfetch{abbreviations}{term}{x}{abbreviation}
    \item Artificial Neural Network : \DTLfetch{abbreviations}{term}{Artificial Neural
    Network}{abbreviation}
    \item x : \DTLfetch{abbreviations}{term}{x}{abbreviation}
\end{itemize}

\end{document}

输出:

在此处输入图片描述

答案1

我认为最简单的方法是使用\DTLgetvalueforkey(并评估/调用定义的宏\DTLgetvalueforkey):

\documentclass{article}

\usepackage{datatool}

\begin{filecontents*}{abbreviationss.csv}
    "term", "abbreviation"
    Machine Learning, ML
    Artificial Neural Network, ANN
\end{filecontents*}

\DTLloaddb{abbreviations}{abbreviationss.csv}

\newcommand{\getabbreviation}[1]{% 
    #1 : %
    \DTLgetvalueforkey{\scratchmacro}{abbreviation}{abbreviations}{term}{#1}%
    \scratchmacro
    %\scratchmacro will be \@dtlnovalue -> "Undefined Value" if #1 is not found.
    % Alternatively:
    % \DTLifnull{\scratchmacro}{Hey, this is undefined!}{\scratchmacro}%
}%

\begin{document}

\begin{itemize}
\item\getabbreviation{x}   
\item\getabbreviation{Machine Learning}
\item\getabbreviation{x}
\item\getabbreviation{Artificial Neural Network}
\item\getabbreviation{x}
\end{itemize}
    
\end{document}

在此处输入图片描述



与 Simon Dispa 的方法类似,其基于\DTLforeach*

\documentclass{article}

\usepackage{datatool}

\begin{filecontents*}{abbreviationss.csv}
    "term", "abbreviation"
    Machine Learning, ML
    Artificial Neural Network, ANN
\end{filecontents*}

\DTLloaddb{abbreviations}{abbreviationss.csv}

\newif\ifnotfound
\global\notfoundtrue

\newcommand{\getabbreviation}[1]{% 
    #1 : %
    \global\notfoundtrue
    \DTLforeach*[{\equal{\term}{#1}}]{abbreviations}{\abbreviation=abbreviation, \term=term}%
                {\abbreviation\global\notfoundfalse\dtlbreak}%
    \ifnotfound Undefined Value\fi
}%

\begin{document}

\begin{itemize}
\item\getabbreviation{x}   
\item\getabbreviation{Machine Learning}
\item\getabbreviation{x}
\item\getabbreviation{Artificial Neural Network}
\item\getabbreviation{x}
\end{itemize}
    
\end{document}

在此处输入图片描述



如果现实生活中的情况不只是关于某些itemize事情,但你真的需要抓住\DTLfetch找不到的情况⟨column1 value⟩

! Package datatool Error: No row found in database `abbreviations' for column ` 1' matching `x'.使用 MWE 时,您会在终端和 .log 文件中发现很多错误。

语法\DTLfetch是:

\DTLfetch{⟨db name⟩}%
         {⟨column1 name⟩}%
         {⟨column1 value⟩}%
         {⟨column2 name⟩}%

部分 ”6.11.1 对当前行进行操作“datatool bundle 2.32 版用户手册中写道:

\dtlgetrowindex{⟨row cs⟩}{⟨db name⟩}{⟨col idx⟩}{⟨value⟩}
类似于,\DTLgetrowindex但如果未找到匹配项,则不会产生错误。您可以使用来测试结果。\ifx⟨row cs⟩\dtlnovalue

因此,您可以编写一个\DTLfetch适用的包装器

\dtlgetrowindex{⟨row cs⟩}%
               {⟨db name⟩}%
               {⟨col idx of column1⟩}%
               {⟨column1 value⟩}%

定义⟨row cs⟩然后执行:

\ifx⟨row cs⟩\dtlnovalue\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
{%
  ⟨ tokens in case ⟨column1 name⟩ does not have a value ⟨column1 value⟩ ⟩%
}{%
  \DTLfetch{⟨db name⟩}{⟨column1 name⟩}{⟨column1 value⟩}{⟨column2 name⟩}%
}%

您需要 column1/of 的索引⟨col idx of column1⟩

您可以通过以下方式获得\dtlcolumnindex{⟨db name⟩}{⟨column1 name⟩}

为了在执行之前扩展参数\dtlgetrowindex——尤其⟨col idx of column1⟩是= —— ,可以定义一个临时宏,通过前面添加阻止命令的扩展和待定义命令的扩展,但不阻止其他参数的扩展,然后调用该临时宏:\dtlcolumnindex{⟨db name⟩}{⟨column1 name⟩}\dtlgetrowindex\protected@edef\dtlgetrowindex⟨row cs⟩\noexpand\dtlgetrowindex

\documentclass{article}

\usepackage{datatool}

%\DTLfetchifcolOneValueExists{<db name>}%
%                            {<column1 name>}%
%                            {<column1 value>}%
%                            {<column2 name>}%
%                            {<tokens in case <column1-value> does not exist>}%
%
%   Turn @ into a normal letter so that it can be used as part of the name of a control sequence:
\makeatletter
%   Test if the command \NewDocumentCommand is not available.
%   If so, use traditional \newcommand.  Otherwise use it.
\@ifundefined{NewDocumentCommand}%
{\newcommand\DTLfetchifcolOneValueExists[5]}%
{\NewDocumentCommand\DTLfetchifcolOneValueExists{mmmmm}}%
{%
  % open a local scope:
  \begingroup
  % define the scratch macro
  \protected@edef\@dtl@dogetrowforvalue{%
    \endgroup\noexpand\dtlgetrowindex{\noexpand\dtl@rowidx}{#1}{\dtlcolumnindex{#1}{#2}}{#3}%
  }%
  % Call the scratch-macro:
  \@dtl@dogetrowforvalue
  % Expansion of the scratch-macro yields:
  %   \endgroup %<-after processing \endgroup the local scope is closed and thus the scratch-macro is undefined.
  %   \dtlgetrowindex{\dtl@rowidx}{<expansion of #1>}{<expansion of \dtlcolumnindex{#1}{#2}>}{<expansion of #3>}%
  %   % After processing \dtlgetrowindex the macro \dtl@rowidx is defined.
  \ifx\dtl@rowidx\dtlnovalue\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
  {#5}{\DTLfetch{#1}{#2}{#3}{#4}}%
}%
\makeatother


% csv file 1
\begin{filecontents*}{abbreviationss.csv}
    term, abbreviation
    Machine Learning, ML
    Artificial Neural Network, ANN
\end{filecontents*}

\DTLloaddb{abbreviations}{abbreviationss.csv}

\begin{document}

\begin{itemize}
    \item x :
          \DTLfetchifcolOneValueExists{abbreviations}%
                                      {term}%
                                      {x}%
                                      {abbreviation}%
                                      {Column `term' doesn't have a value `x'}
    \item Machine Learning :
          \DTLfetchifcolOneValueExists{abbreviations}%
                                      {term}%
                                      {Machine Learning}%
                                      {abbreviation}%
                                      {Column `term' doesn't have a value `Machine Learning'}
    \item x : 
          \DTLfetchifcolOneValueExists{abbreviations}%
                                      {term}%
                                      {x}%
                                      {abbreviation}%
                                      {\DTLstringnull}
    \item Artificial Neural Network :
          \DTLfetchifcolOneValueExists{abbreviations}%
                                      {term}%
                                      {Artificial Neural Network}%
                                      {abbreviation}%
                                      {Column `term' doesn't have a value `Artificial Neural Network'}
    \item x :
          \DTLfetchifcolOneValueExists{abbreviations}%
                                      {term}%
                                      {x}%
                                      {abbreviation}%
                                      {\dtlnovalue}
\end{itemize}

\end{document}

在此处输入图片描述

如果您希望获得一些空值而不是短语“列'term'没有值'x'”,您可以提供其中一个标记/ \DTLstringnull/。(yields。yields。yields \DTLnumbernull。所有三个标记都可以用作等的第一个参数\dtlnovalue。)\DTLstringnullNULL\DTLnumbernull0\dtlnovalueUndefined Value\DTLifnull

答案2

每次找到a 时,该命令\itemx都会生成一个新的。否则它什么也不做。\itemterm

输出:

A

\documentclass{article}

\usepackage{datatool}

\begin{filecontents*}{abbreviationss.csv}
    "term", "abbreviation"
    Machine Learning, ML
    Artificial Neural Network, ANN
\end{filecontents*}

\DTLloaddb{abbreviations}{abbreviationss.csv}

\begin{document}

\newcommand{\itemx}[1]{% added <<<<
    \DTLforeach*{abbreviations}{\abbreviation=abbreviation, \term=term}
    {\ifthenelse{\equal{\term}{#1}} 
    {\item \term:   \abbreviation } {}}
            }

\begin{itemize}
    \itemx{x}   
    \itemx{Machine Learning}
    \itemx{x}
    \itemx{Artificial Neural Network}
    \itemx{x}
\end{itemize}
    
\end{document}

选择(更快且有警告)

使用\DTLassignfirstmatch并转变\PackageError\PackageWarning

X

\documentclass{article}

\usepackage{datatool}

    
\begin{filecontents*}{abbreviationss2.csv}
    "term", "abbreviation"
    Machine Learning, ML
    Artificial Neural Network, ANN
    Artificial Intelligence, AI
\end{filecontents*}

\DTLloaddb{abbreviations}{abbreviationss2.csv}

\newcommand{\term}{}
\newcommand{\abbreviation}{}

\makeatletter   
\renewcommand*{\dtl@assignfirstmatch}[4]{%
    \DTLifdbexists{#2}%
    {%
        {%
            \dtlgetrowindex{\dtl@asg@rowidx}{#2}{\dtlcolumnindex{#2}{#3}}{#1}%
            \ifx\dtl@asg@rowidx\dtlnovalue%
            \PackageWarning{datatool}{No match found for \string\DTLassignfirstmatch{#2}{#3}{#1}{#4}}{}%
            \else
            \dtlgetrow{#2}{\dtl@asg@rowidx}%
            \@dtl@assign{#4}{#2}%
            \fi
        }%
    }%
    {%
        \PackageError{datatool}{Data base `#2' doesn't exist}{}%
    }%
}

\makeatother

    \newcommand{\itemx}[1]{%
    \renewcommand{\term}{}%
    \renewcommand{\abbreviation}{}%
    \DTLassignfirstmatch{abbreviations}{term}{#1}{\term=term,\abbreviation=abbreviation}%
    \ifthenelse{\equal{\abbreviation}{}}{\item #1:~(\dtlnovalue)}{\item #1:~(\abbreviation)}%
}

\newcommand{\findx}[1]{%
    \renewcommand{\term}{}%
    \renewcommand{\abbreviation}{}%
    \DTLassignfirstmatch{abbreviations}{term}{#1}{\term=term,\abbreviation=abbreviation}%
    \ifthenelse{\equal{\abbreviation}{}}{~(\dtlnovalue)}{~(\abbreviation)}%
}

\begin{document}
    
    \DTLdisplaydb{abbreviations}
    \bigskip
    
    \begin{itemize}
        \itemx{x}   
        \itemx{Machine Learning}
        \itemx{x}
        \itemx{Artificial Neural Network}
        \itemx{x}
    \end{itemize}
    
    \bigskip
    
    
    Deep Learning\findx{Deep Learning} is a subset of Artificial Neural Network\findx{Artificial Neural Network},
    which in turn is a subset of Machine Learning\findx{Machine Learning} and
     Artificial Intelligence\findx{Artificial Intelligence}.    
    
\end{document}

相关内容