如何将宏应用于表格的每一行

如何将宏应用于表格的每一行

这类似于关于细胞的问题,但有整行,希望能帮助我实现答案这个问题

给定一个宏\RowMacro,我如何定义mytable环境以便我可以在我的文档中写入

\begin{mytable}
a & b & c \\
d & e & f \\
g \\
h & i & j
\end{mytable}

得到的结果和我写的一样

\RowMacro{a}{b}{c}
\RowMacro{d}{e}{f}
\RowMacro{g}{}{}
\RowMacro{h}{i}{j}

可能必须预先指定最大列数。

答案1

environ用于捕获环境的内容。LaTeX3 代码(包expl3)将其拆分为行、单元格和更通用的编程工具。与其像我一样创建一个具有 4 个参数的环境,不如在定义中对其中一些参数进行硬编码(如果更实用的话)。

\documentclass{article}
\usepackage{environ}
\usepackage{expl3}
\ExplSyntaxOn
\seq_new:N \l_jb_lines_seq
\seq_new:N \l_jb_tmp_seq
\tl_new:N \l_jb_result_tl
\int_new:N \l_jb_cols_int
\int_new:N \l_jb_cell_int
\tl_new:N \l_jb_one_line_tl
\NewEnviron{mytable}[4][]
  {
    \seq_set_split:NnV \l_jb_lines_seq { \\ } \BODY
    %
    % If the user gives no indication of number of cells, find the max
    % number by reading all rows.  Otherwise, use the user-given value,
    % all extras will be thrown out silently.
    %
    \tl_if_empty:nTF {#1}
      { \jb_get_max_cells:NN \l_jb_lines_seq \l_jb_cols_int }
      { \int_set:Nn \l_jb_cols_int {#1} }
    %
    % Build the result into a token list, initially the begin-code |#3|.
    % For each line |##1|, add a call to the command |#2| with exactly
    % |\l_jb_cols_int| arguments.  Then append the end-code |#4|.
    % Finally, use the token list.
    %
    \tl_set:Nn \l_jb_result_tl {#3}
    \seq_map_inline:Nn \l_jb_lines_seq
      { \jb_append_one_line:NnNn \l_jb_result_tl {#2} \l_jb_cols_int {##1} }
    \tl_put_right:Nn \l_jb_result_tl {#4}
    \tl_use:N \l_jb_result_tl
  }
\cs_new_protected:Npn \jb_get_max_cells:NN #1#2
  {
    % Find the max number of cells over all lines.
    % Not terribly efficient way of counting |&|: split at each |&|
    % and store in a tmp sequence, then count its items.
    %
    \int_zero:N #2
    \seq_map_inline:Nn #1
      {
        \seq_set_split:Nnn \l_jb_tmp_seq { & } {##1}
        \int_set:Nn #2
          { \int_max:nn #2 { \seq_count:N \l_jb_tmp_seq } }
      }
  }
\cs_new_protected:Npn \jb_append_one_line:NnNn #1#2#3#4
  {
    \tl_set:Nn \l_jb_one_line_tl {#2}
    \seq_set_split:Nnn \l_jb_tmp_seq { & } {#4}
    \int_set:Nn \l_jb_cell_int { \seq_count:N \l_jb_tmp_seq }
    \int_compare:nNnTF \l_jb_cell_int > {#3}
      {
        \int_zero:N \l_jb_cell_int
        \seq_map_inline:Nn \l_jb_tmp_seq
          {
            \int_compare:nNnF \l_jb_cell_int < {#3} { \seq_map_break: }
            \int_incr:N \l_jb_cell_int
            \tl_put_right:Nn \l_jb_one_line_tl { {##1} }
          }
      }
      {
        \seq_map_inline:Nn \l_jb_tmp_seq
          { \tl_put_right:Nn \l_jb_one_line_tl { {##1} } }
        \tl_put_right:Nx \l_jb_one_line_tl
          { \prg_replicate:nn { #3 - \l_jb_cell_int } { { } } }
      }
    \tl_put_right:NV #1 \l_jb_one_line_tl
  }
\ExplSyntaxOff
\begin{document}
\newcommand{\RowMacro}[5]{[1: #1] & [2: #2] & [3 and 4: #3, #4] & [5: #5]\\}
\begin{mytable}[5]{\RowMacro}{\begin{tabular}{cccc}}{\end{tabular}}
  a & b & c \\
  d & e & f & g & h & extra\notused \\
  ijk & l
\end{mytable}
\end{document}

答案2

一个简单的解决方案,如果你知道列数:

\def\RowMacroIII{{#1}&{#2}&{#3}\\}

用法

\RowMacro{a}{b}{c}

\def\RowMacroIV{{#1}&{#2}&{#3}&{#4}\\}

用法

\RowMacro{a}{b}{c}{d}

相关内容