Expl3 简化循环构建 Tabularray 内容的扩展问题

Expl3 简化循环构建 Tabularray 内容的扩展问题

后续我之前的问题感谢@egreg 的回答。(也许 Gregorio 教授也能在这里帮助我。)

情况

我正在创建一个问题表 (ToQ) 宏,用于在考试或作业的封面上创建标记表。它工作得很好,tabular但我换成了 Tabularray 的tblr,我爱上了它。不幸的是,因为我习惯于totcount在遇到每个新问题时为其分数创建计数器,所以我遇到了扩展问题,今天这些问题让我很困惑。

问题

循环不能放在tblr环境中(参见§3.2.3手册中的说明),就像普通表格的情况一样。但似乎适用于普通表格的解决方案:

  • 使用 LaTeX 原始循环,
  • 在表格外部构建由 \edefs 组成的 \gdef,并且
  • 将主体构建为一个令牌登记册,

尚未对 起作用tblr。此外,tblr还允许指定一个expand选项,在处理正文之前指定要扩展的标记。(我将在后面的 MWE 中展示这一点。)

我想要的

受到@frougon 答案的启发这里,我想采用完全 expl3 的方法,因为我无论如何都在尝试学习 expl3。但我不知所措,希望得到一些帮助。不仅仅是一个解决方案,如果您能帮忙的话,我想要一个简要的概述,这样我就可以通过抓取文档来研究解决方案。

平均能量损失

\documentclass{article}
\usepackage{tabularray}
\usepackage{xcolor}

\usepackage{totcount}

% Stuff for keeping account of questions and their scores
% ........................................................<<<
\newcounter{questioncount}
\setcounter{questioncount}{0}
\regtotcounter{questioncount}%
\newcounter{scoretotal}
\setcounter{scoretotal}{0}
\regtotcounter{scoretotal}%

\newcommand{\setquestionpoints}[2]{%
  \expanded{\noexpand\newtotcounter{qpoints#1}}%
  \expanded{\noexpand\setcounter{qpoints#1}}{#2}%
}
\newcommand{\getquestionpoints}[1]{%
  \ifnum\value{qpoints#1}>0
    \arabic{qpoints#1}%
  \else
    0%
  \fi
}

\newcommand{\TOTAL}[1]{%
  \ifcsname c@#1@totc\endcsname
    \total{#1}%
  \else
    ??%
  \fi
}
% ........................................................>>>

% Typesetting questions
% ........................................................<<<
\newcommand{\nquestion}[1]{%
  \stepcounter{questioncount}%
  \setquestionpoints{\arabic{questioncount}}{#1}%
  \addtocounter{scoretotal}{#1}%
  Question~\thequestioncount (#1 marks.)%
}
% ........................................................>>>

\ExplSyntaxOn

\cs_new_protected:Npn \my_typeset_table_generic:nn #1#2
  {
    \group_begin:
      \cs_set_protected:Npn \__my_typeset_table_generic_tmp_func:n ##1 {#1}
      \__my_typeset_table_generic_tmp_func:n {#2}
    \group_end:
  }

\cs_generate_variant:Nn \my_typeset_table_generic:nn { nV }

\ExplSyntaxOff

\begin{document}

\ExplSyntaxOn

% This works, but I would like to know how expl3 can help me build this
%  list automatically, looping for
%      q ∈ [1, \totvalue{questioncount}]
%  to obtain \TOTAL{qpoints\theq} in each cell of the middle column.
\tl_set:Nn \l_my_tabular_tl {%
    1 & \TOTAL{qpoints1} & \null \\ \hline
    2 & \TOTAL{qpoints2} & \null \\ \hline
    3 & \TOTAL{qpoints3} & \null \\ \hline
}
\my_typeset_table_generic:nV
  {
    \SetTblrInner{rowsep=1ex}%
    \begin{tblr}{colspec={|ccX[c]|}, width=0.35\linewidth}
      \SetRow{black, rowsep=0.25ex}
      \color{white}\textit{Q}\textnumero & \color{white}Marks & \color{white}Grade \\ \hline
      #1
    \SetCell[c=2]{c}~TOTAL:~&~\null\\\cline[r]{3-3}
           && {\TOTAL{scoretotal}}\\\hline
    \end{tblr}
  }
  \l_my_tabular_tl
\ExplSyntaxOff

%%% Make some questions:
\vspace{2cm}
\noindent
\nquestion{10}\\
\nquestion{12}\\
\nquestion{15}\\


\end{document}

生成:

答案1

最后\\导致\nquestion{15}了 Badbox,因此将其删除。

环境可以放在 expl3 代码之外。使用环境中的tblr选项。然后不再需要。expandtblr\my_typeset_table_generic:nn

tblr环境中,选项rowsep=1ex放在选项列表中,第一行的设置用 键确定row{1}。那么就不需要写\color{white}三次了。

\null已被删除。

周围的括号\TOTAL{scoretotal}已被拆除。

在命令中\nquestion{}后面添加\thequestioncount, 以便括号不会紧跟在数字后面。

\l_my_tabular_tl未使用 进行初始化\tl_new:N。现在已使用 进行初始化\tl_new:N \tblrbody

内容以 收集\tl_build_put_right:Nn。此过程以 开始\tl_build_begin:N并以 结束\tl_build_end:N

由于初始值已经是0,所以\setcounter{questioncount}{0}后面不需要再加。\newcounter{questioncount}

不使用\newcounter和,而可以使用\regtotcounter简写。\newtotcounter

无需定义命令\TOTAL。它由 代替\total

命令\setquestionpoints集成在命令 中\nquestion。此处,\arabic{questioncount}替换为\thequestioncount。对于\setcounter\expanded\noexpand是不必要的。

在 之后\SetCell&添加了 ,因为使用\SetCell,所以不能删除省略的单元格。

在此处输入图片描述

\documentclass{article}
\usepackage{xcolor}
\usepackage{tabularray}

\usepackage{totcount}

% Stuff for keeping account of questions and their scores
% ........................................................<<<
\newtotcounter{questioncount}
\newtotcounter{scoretotal}

\newcommand{\getquestionpoints}[1]{%
  \ifnum\value{qpoints#1}>0
    \arabic{qpoints#1}%
  \else
    0%
  \fi
}

% ........................................................>>>

% Typesetting questions
% ........................................................<<<
\newcommand{\nquestion}[1]{%
  \stepcounter{questioncount}%
  \expanded{\noexpand\newtotcounter{qpoints\thequestioncount}}%
  \setcounter{qpoints\thequestioncount}{#1}%
  \addtocounter{scoretotal}{#1}%
  Question~\thequestioncount{} (#1 marks.)%
}
% ........................................................>>>


\begin{document}
\ExplSyntaxOn
\tl_new:N \tblrbody
\tl_build_begin:N \tblrbody
\int_step_inline:nn { \totvalue { questioncount } }
  {
    \tl_build_put_right:Nn \tblrbody { #1 & \total { qpoints#1 } & \\ \hline }
  }
\tl_build_end:N \tblrbody
\ExplSyntaxOff
\begin{tblr}[expand=\tblrbody]{
  colspec={|ccX[c]|},
  width=0.35\linewidth,
  rowsep=1ex,
  row{1}={bg=black,fg=white,rowsep=0.25ex}
}
\emph{Q}\textnumero & Marks & Grade\\\hline
\tblrbody
\SetCell[c=2]{c} ~TOTAL:~ & & \\\cline[r]{3-3}
 & & \total{scoretotal}\\\hline
\end{tblr}


%%% Make some questions:
\vspace{2cm}
\noindent
\nquestion{10}\\
\nquestion{12}\\
\nquestion{15}


\end{document}

答案2

我找到了一个解决方案,其中我在 expl3 中构建了宏的行。我认为这不是最优雅的,但它有效。我对改进它的提示/评论很感兴趣,所以我不接受这个答案,看看是否有人能提出一些漂亮的东西。

\ExplSyntaxOn
\NewDocumentCommand{\ToQ}{}{
  \tl_set:Nn \l_tmpa_tl {
    \SetTblrInner{rowsep=1ex}%
    \begin{tblr}[b]{colspec={|ccX[c]|}, width=0.35\linewidth}
      \SetRow{black, rowsep=0.25ex}
      \color{white}\textit{Q}\textnumero
        & \color{white}Marks
          & \color{white}Grade \\ \hline
  }
  \int_step_inline:nn {\totvalue{questioncount}} {
      \tl_put_right:Nn \l_tmpa_tl { ##1 & \fromaux{qpoints##1} & \null \\ \hline }
  }
  \tl_put_right:Nn \l_tmpa_tl {
      \SetCell[c=2]{c}~TOTAL:~&~\null\\\cline[r]{3-3}
      && {\fromaux{scoretotal}}\\\hline
    \end{tblr}
  }
  \l_tmpa_tl
}
\ExplSyntaxOff

生产

在此处输入图片描述

答案3

生活不必那么复杂。始终要明确输入和输出的格式。即提供 API。

  1. 您不需要 LaTeX2e 计数器,请使用模块int
  2. 当您想要存储值时,请考虑csname
  3. 创建一系列命令\Q1..\Qn存储值,就\Q1-marks好像您希望的那样,您也可以\Q1-question存储实际的问题。

这是一个快速解决方案。我使用了表格,只是为了演示概念。通常我会尽量减少使用的软件包。请修改以向 l3 命令添加前缀,这是很好的做法。

输出

\documentclass{article}
%------------------------------------------------------------
% INPUT : \AddQuestion{name}{marks}
% OUTPUT: PrintScoreSheet  
%------------------------------------------------------------
\ExplSyntaxOn
\int_new:N \g_questions_total_int
\clist_new:N \g_questions_clist
\prop_new:N \g_questions_marks_prop
\cs_new_protected:Npn \questions_add:nn  #1 #2
  {
    \clist_gput_right:Nn \g_questions_clist {#1}
    \prop_gput:Nnn \g_questions_marks_prop {#1} {#2}
  }

\cs_new_protected:Npn \questions_printlist:
  {
    \begin{tabular}{lrr}
      \hline
      \clist_map_inline:Nn \g_questions_clist
        {
          \prop_get:NnN \g_questions_marks_prop {##1} \l_tmpa_tl
          \int_gadd:Nn \g_questions_total_int { \l_tmpa_tl } 
           ##1  &  \use:c{##1-marks} &\\  %Row
        }
      \\\noalign{\vskip-10pt}
      \cline{2-3} 
      Total & \int_use:N\g_questions_total_int &\\ 
      \hline
    \end{tabular}
  }
\let\AddQuestion\questions_add:nn
\let\PrintScoreSheet\questions_printlist:

\ExplSyntaxOff
\begin{document}
\AddQuestion {Q1}{10}
\AddQuestion {Q2}{20}
\AddQuestion {Q3}{5}
\AddQuestion{Q4}{5}
\PrintScoreSheet
\end{document}

相关内容