问题陈述

问题陈述

问题陈述

我使用datatool包的宏从 .csv 文件中\xDTLassignfirstmatch确定给定作业的截止日期(由短代码标识,例如ex1或),该文件包含一列(讲座日期列表)和一列(显示在相应日期截止的作业)。rd2DateDue

只要每堂课只交一份作业,这种方法就很好。然而,由于\xDTLassignfirstmatch需要精确的,而不是部分匹配,如果在同一日期有多个作业到期,则匹配失败。

所以问题是:即使一个或多个其他作业也在同一天截止,我如何从 .csv 数据中确定特定作业的截止日期?

最小(非)工作示例

将以下代码复制到一个文件中main.tex,并用 进行编译pdflatex main。然后记下TODO文件中的注释并进行相应的编辑。

主文本

\documentclass{article}

\usepackage{datatool}

\begin{filecontents}{schedule.csv}
Date,Due
2016-02-03,
2016-02-08,rd1
2016-02-10,"ex1, rd2"
\end{filecontents}

% NOTE:  Uncomment only one of the following three lines at a time
\def\assignment{rd1}% Works, because no other assignment is due that day
%\def\assignment{ex1}% TODO: Breaks compilation, because rd2 is due the same day
%\def\assignment{rd2}% TODO: Breaks compilation, because ex1 is due the same day

\DTLloaddb{schedule}{schedule.csv}%
\xDTLassignfirstmatch{schedule}{Due}{\assignment}{\date=Date}%

\begin{document}

\noindent Date: \date

\end{document}

限制

我希望schedule.csv尽可能保持结构一致。但是,如果有助于解决问题,应该可以用空格代替逗号(用于分隔当天截止的作业)。

对可能的解决方案的想法

\DTLifSubString \DTLisinlist包中的宏可能datatool有助于解决这个问题,但我认为主要的挑战是用\xDTLassignfirstmatch一些只需要部分匹配而不是完全匹配的宏来替换。我很确定这不存在,datatool但必须从头开始编写(或从其他包中获取)?

Ulrike 原始解决方案的后续问题

Ulrike 提出了一种xparse基于 的解决方案,该解决方案适用于给定的 MWE,但不适用于我的实际项目,因为一旦提取了作业截止日期,我实际上会使用它从 中提取更多数据schedule.csv

为了说明这一点,我添加了一个经过编辑的 MWE,它基于 Ulrike 的原始解决方案,但编译失败(参见TODO文件中的注释)并出现错误Undefined control sequence。我正在寻找一种方法来编译这个新的 MWE。

\documentclass{article}

\usepackage{datatool,xparse}

\begin{filecontents}{schedule.csv}
Date,Due,Foo
2016-02-03,,Bla
2016-02-08,rd1,Moo
2016-02-15,"ex1,rd3",Ha
2016-02-10,"ex1, rd2",Zoo
\end{filecontents}

\DTLloaddb{schedule}{schedule.csv}%

\ExplSyntaxOn


\DTLforeach{schedule}{\scheduledate=Date,\scheduledue=Due}
 {
  \clist_set:NV\l_tmpa_clist{\scheduledue} 
  %\clist_show:N\l_tmpa_clist
  \clist_map_inline:Nn\l_tmpa_clist
   {
    \tl_if_exist:cF
    { g_firstschedule_#1_tl }
    {
     \tl_new:c    {g_firstschedule_#1_tl}
     \tl_gset:cV  {g_firstschedule_#1_tl}{\scheduledate}
    }
   }
 }
\NewDocumentCommand\firstassignment { m }
{
 \tl_use:c {  g_firstschedule_#1_tl } 
}


\ExplSyntaxOff
\begin{document}

Date rd1: \firstassignment {rd1}

Date rd2: \firstassignment {rd2}

Date ex1: \firstassignment {ex1}

Date rd3: \firstassignment {rd3}

% TODO: The following line breaks compilation
\xDTLassignfirstmatch{schedule}{Date}{\firstassignment{rd1}}{\myfoo=Foo}%

\end{document}

答案1

您可以处理数据并检索日期。但请注意,如果您有大量条目,速度可能会变慢。

\documentclass{article}

\usepackage{datatool,xparse}

\begin{filecontents}{schedule.csv}
Date,Due
2016-02-03,
2016-02-08,"rd1"
2016-02-10,"ex1, rd2"
2016-02-15,"ex1,rd3"
\end{filecontents}

\DTLloaddb{schedule}{schedule.csv}%

\ExplSyntaxOn


\DTLforeach{schedule}{\scheduledate=Date,\scheduledue=Due}
 {
  \clist_set:NV\l_tmpa_clist{\scheduledue} 
  %\clist_show:N\l_tmpa_clist
  \clist_map_inline:Nn\l_tmpa_clist
   {
    \tl_if_exist:cF
    { g_firstschedule_#1_tl }
    {
     \tl_new:c    {g_firstschedule_#1_tl}
     \tl_gset:cV  {g_firstschedule_#1_tl}{\scheduledate}
    }
   }
 }

\NewDocumentCommand\firstassignment { m }
{
 \tl_use:c {  g_firstschedule_#1_tl } 
}


\ExplSyntaxOff
\begin{document}

Date rd1: \firstassignment {rd1}

Date rd2: \firstassignment {rd2}

Date ex1: \firstassignment {ex1}

Date rd3: \firstassignment {rd3}
\end{document}

编辑以便后续跟进。

\xDTLassignfirstmatch只扩展一次,因此您不能使用复杂的命令,您需要先将值存储在一些简单的宏中。此外,\NewDocumentCommand 会创建不可扩展的健壮命令。因此,为了让您的后续工作正常进行,最好使用 \newcommand:

\documentclass{article}

\usepackage{datatool,xparse}


\DTLloaddb{schedule}{schedule.csv}%

\ExplSyntaxOn


\DTLforeach{schedule}{\scheduledate=Date,\scheduledue=Due}
 {
  \clist_set:NV\l_tmpa_clist{\scheduledue}
  %\clist_show:N\l_tmpa_clist
  \clist_map_inline:Nn\l_tmpa_clist
   {
    \tl_if_exist:cF
    { g_firstschedule_#1_tl }
    {
     \tl_new:c    {g_firstschedule_#1_tl}
     \tl_gset:cV  {g_firstschedule_#1_tl}{\scheduledate}
    }
   }
 }
\newcommand\firstassignment[1]
{
 \tl_use:c {  g_firstschedule_#1_tl }
}

\ExplSyntaxOff
\begin{document}

Date rd1: \firstassignment {rd1}

Date rd2: \firstassignment {rd2}

Date ex1: \firstassignment {ex1}

Date rd3: \firstassignment {rd3}


\edef\tmpdate{\firstassignment{rd1}}
\xDTLassignfirstmatch{schedule}{Date}{\tmpdate}{\myfoo=Foo}%
\myfoo

\end{document}

相关内容