将 ExplSyntaxOn 中 \newdocumentcommand 的分隔符设置为管道 |(默认为逗号)

将 ExplSyntaxOn 中 \newdocumentcommand 的分隔符设置为管道 |(默认为逗号)

在主题的代码中我想创建一个新的命令来制作表格,命令中的参数将填充表格

分隔符是逗号:

\cards{3,1,6,1,2,2,3,2,4,3,4,3,5,7,5,4}

但在我的数据中,有很多条目包含逗号:例如“红色,蓝色T恤”

我怎样才能将分隔符更改为管道符|,以便可以输入以下内容?

\cards{3|1|6|1|2|2|3|2|4|3|4|3|5|7|5|4}

最小代码:

\documentclass{article}
\usepackage{booktabs}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\cards}{ m }
 {
  \arne_card_distribution:n { #1 }
 }

\cs_new_protected:Nn \arne_card_distribution:n
 {
  \begin{tabular}{ *{5}{c} }
  \toprule
  & lente & zomer & herfst & winter \\
  \cmidrule{2-5}
  B & \clist_item:nn { #1 } { 1 }
    & \clist_item:nn { #1 } { 2 }
    & \clist_item:nn { #1 } { 3 }
    & \clist_item:nn { #1 } { 4 } \\
  G & \clist_item:nn { #1 } { 5 }
    & \clist_item:nn { #1 } { 6 }
    & \clist_item:nn { #1 } { 7 }
    & \clist_item:nn { #1 } { 8 } \\
  D & \clist_item:nn { #1 } { 9 }
    & \clist_item:nn { #1 } { 10 }
    & \clist_item:nn { #1 } { 11 }
    & \clist_item:nn { #1 } { 12 } \\
  S & \clist_item:nn { #1 } { 13 }
    & \clist_item:nn { #1 } { 14 }
    & \clist_item:nn { #1 } { 15 }
    & \clist_item:nn { #1 } { 16 } \\
  \bottomrule
  \end{tabular}
 }
\ExplSyntaxOff

\begin{document}

\cards{3,1,6,1,2,2,3,2,4,3,4,3,5,7,5,4}


\end{document}

答案1

这是表格的一个略微(过度?)修改过的版本。我让它在行数和列数方面更加灵活。

\cards命令现在接受一个可选参数和三个强制参数:

\cards[<key-val>]{<header row>}{<first column>}{<table body>}

可选参数允许您使用sep=<sep>(默认为) 设置分隔符并使用(默认为) 设置sep=|表格单元格的对齐方式。是一个以 分隔的项目列表,将排版在表格顶部,前面有一个空单元格。也是一个以 分隔的项目列表,将排版在表格的每一行,从第二行开始。align=<token>align=c<header row><sep><first column><sep>

<table body>一个<sep>以 - 分隔的列表M×N项目 (MN<header row>是和列表中的项目数<first column>),这些项目将按行主顺序逐个添加到表中(即第一个M项目放在第一行,下一行M物品放在第二行,依此类推。

您问题中的表格可以这样排版(为清楚起见添加了换行符;项目周围的空格被修剪):

\cards{ lente | zomer | herfst | winter }
      { B | G | D | S }
      {3|1|6|1|
       2|2|3|2|
       4|3|4|3|
       5|7|5|4}

使用选项的示例:

\cards[sep = /, align = l]
  { foo / bar / baz }
  { F   / B   / B }
  {1/2/3/
   4/5/6/
   7/8/9}

输出:

在此处输入图片描述

代码:

\documentclass{article}
\usepackage{booktabs}
\usepackage{xparse}

\ExplSyntaxOn
\tl_new:N \l__forti_table_sep_tl
\tl_new:N \l__forti_table_align_tl
\tl_new:N \l__forti_table_temp_tl
\int_new:N \l__forti_table_ncols_int
\seq_new:N \g__forti_table_body_seq
\seq_new:N \g__forti_table_header_seq
\seq_new:N \g__forti_table_column_seq
\cs_generate_variant:Nn \seq_gset_split:Nnn { Nx }
\keys_define:nn { forti }
  {
    , sep .tl_set:N = \l__forti_table_sep_tl
    , sep .initial:n = { | }
    , sep .value_required:n = true
    , align .tl_set:N = \l__forti_table_align_tl
    , align .initial:n = { c }
    , align .value_required:n = true
  }
\NewDocumentCommand { \cards } { o m m m }
  {
    \group_begin:
      \IfValueT {#1} { \keys_set:nn { forti } {#1} }
      \forti_card_distribution:nnn {#2} {#3} {#4}
    \group_end:
  }
\cs_new_protected:Npn \forti_card_distribution:nnn #1 #2 #3
  {
    \__forti_seq_gset_split:Nn \g__forti_table_header_seq {#1}
    \__forti_seq_gset_split:Nn \g__forti_table_column_seq {#2}
    \__forti_seq_gset_split:Nn \g__forti_table_body_seq   {#3}
    \__forti_card_distribution_check_do:nnnN
      { \seq_count:N \g__forti_table_header_seq }
      { \seq_count:N \g__forti_table_column_seq }
      { \seq_count:N \g__forti_table_body_seq }
    \__forti_card_distribution:nn
  }
\cs_new_protected:Npn \__forti_seq_gset_split:Nn #1 #2
  { \seq_gset_split:Nxn #1 { \tl_use:N \l__forti_table_sep_tl } {#2} }
\cs_new_protected:Npn \__forti_card_distribution_check_do:nnnN #1 #2 #3 #4
  {
    \int_compare:nNnTF {#1*#2} = {#3}
      { #4 {#1} {#2} }
      {
        \msg_error:nnxx { forti } { wrong-number-of-items }
          { \int_eval:n {#1*#2} } {#3}
      }
  }
\cs_new_protected:Npn \__forti_card_distribution:nn #1 #2
  {
    \int_set:Nn \l__forti_table_ncols_int {#1}
    \use:x
      {
        \exp_not:N \begin{tabular}
          { * { \int_eval:n {#1 + 1} } { \tl_use:N \l__forti_table_align_tl } }
      }
      \toprule
        \c_alignment_token
        \seq_use:Nn \g__forti_table_header_seq { \c_alignment_token } \\
      \cmidrule { 2 - \int_eval:n {#1 + 1} }
        \int_step_function:nN { #2 }
          \__forti_typeset_table_row:n
      \bottomrule
    \end{tabular}
  }
\cs_new_protected:Npn \__forti_typeset_table_row:n #1
  {
    \seq_gpop:NN \g__forti_table_column_seq \l__forti_table_temp_tl
    \tl_use:N \l__forti_table_temp_tl
    \int_step_function:nN { \int_use:N \l__forti_table_ncols_int }
      \__forti_typeset_table_item:n
    \\
  }
\cs_new_protected:Npn \__forti_typeset_table_item:n #1
  {
    \seq_gpop:NN \g__forti_table_body_seq \l__forti_table_temp_tl
    \use:x { \c_alignment_token \exp_not:V \l__forti_table_temp_tl }
  }
\msg_new:nnn { forti } { wrong-number-of-items }
  { Wrong~number~of~items~`#2'.~The~table~has~`#1'~cells. }
\ExplSyntaxOff

\begin{document}

\cards{ lente | zomer | herfst | winter }
      { B | G | D | S }
      {3|1|6|1|
       2|2|3|2|
       4|3|4|3|
       5|7|5|4}

\cards[sep = /, align = l]
  { foo / bar / baz }
  { F   / B   / B }
  {1/2/3/
   4/5/6/
   7/8/9}

\end{document}

根据要求,这是一个没有第一列的版本:

在此处输入图片描述

\documentclass{article}
\usepackage{booktabs}
\usepackage{xparse}

\ExplSyntaxOn
\tl_new:N \l__forti_table_sep_tl
\tl_new:N \l__forti_table_align_tl
\tl_new:N \l__forti_table_temp_tl
\int_new:N \l__forti_table_ncols_int
\seq_new:N \g__forti_table_body_seq
\seq_new:N \g__forti_table_header_seq
\cs_generate_variant:Nn \seq_gset_split:Nnn { Nx }
\keys_define:nn { forti }
  {
    , sep .tl_set:N = \l__forti_table_sep_tl
    , sep .initial:n = { | }
    , sep .value_required:n = true
    , align .tl_set:N = \l__forti_table_align_tl
    , align .initial:n = { c }
    , align .value_required:n = true
  }
\NewDocumentCommand { \cards } { o m m }
  {
    \group_begin:
      \IfValueT {#1} { \keys_set:nn { forti } {#1} }
      \forti_card_distribution:nn {#2} {#3}
    \group_end:
  }
\cs_new_protected:Npn \forti_card_distribution:nn #1 #2
  {
    \__forti_seq_gset_split:Nn \g__forti_table_header_seq {#1}
    \__forti_seq_gset_split:Nn \g__forti_table_body_seq   {#2}
    \__forti_card_distribution_check_do:nnN
      { \seq_count:N \g__forti_table_header_seq }
      { \seq_count:N \g__forti_table_body_seq }
    \__forti_card_distribution:nn
  }
\cs_new_protected:Npn \__forti_seq_gset_split:Nn #1 #2
  { \seq_gset_split:Nxn #1 { \tl_use:N \l__forti_table_sep_tl } {#2} }
\cs_new_protected:Npn \__forti_card_distribution_check_do:nnN #1 #2 #3
  {
    \int_compare:nNnTF { \int_mod:nn {#2}{#1} } = { 0 }
      { #3 {#1} {#2} }
      { \msg_error:nnxx { forti } { wrong-number-of-items } {#1} {#2} }
  }
\cs_new_protected:Npn \__forti_card_distribution:nn #1 #2
  {
    \int_set:Nn \l__forti_table_ncols_int {#1}
    \use:x
      {
        \exp_not:N \begin{tabular}
          { * { \int_eval:n {#1} } { \tl_use:N \l__forti_table_align_tl } }
      }
      \toprule
        \seq_use:Nn \g__forti_table_header_seq { \c_alignment_token } \\
      \midrule
        \int_step_function:nN { #2/#1 }
          \__forti_typeset_table_row:n
      \bottomrule
    \end{tabular}
  }
\cs_new_protected:Npn \__forti_typeset_table_row:n #1
  {
    \int_step_function:nN { \l__forti_table_ncols_int }
      \__forti_typeset_table_item:n
    \\
  }
\cs_new_protected:Npn \__forti_typeset_table_item:n #1
  {
    \seq_gpop:NN \g__forti_table_body_seq \l__forti_table_temp_tl
    \use:x
      {
        \int_compare:nNnT {#1} > { 1 } { \c_alignment_token }
        \exp_not:V \l__forti_table_temp_tl
      }
  }
\msg_new:nnn { forti } { wrong-number-of-items }
  { Wrong~number~of~items~`#2'.~The~table~has~`#1'~cells. }
\ExplSyntaxOff

\begin{document}

\cards{ lente | zomer | herfst | winter }
      {3|1|6|1|
       2|2|3|2|
       4|3|4|3|
       5|7|5|4}

\cards[sep = /, align = l]
  { foo / bar / baz }
  {1/2/3/
   4/5/6/
   7/8/9}

\end{document}

相关内容