如何使用字符串变量并返回数组制作宏?

如何使用字符串变量并返回数组制作宏?

我想创建一个宏“\mymacro”,它有两个字符串变量并返回数组。

这两个变量是任意字符串字符,长度相同。字符串的长度也是任意的。“\mymacro”返回一个数组,其行是字符串变量。例如,

\mymacro{abc}{def}

应该返回

\begin{array}{ccc}
   a&b&c\\\hline
   d&e&f
\end{array}

我可以做这样的宏吗?谢谢合作。

答案1

您可以遍历列表,棘手的一点是避免&在末尾添加,我确实添加了它,但用来\omit避免生成可见的空列(带有过长的\hline

在此处输入图片描述

\documentclass{article}

\usepackage{amsmath}

\newcommand\mymacro[2]{\begin{matrix}\zz#1\zzz\\\hline\zz#2\zzz\end{matrix}}


\def\zz#1{#1&\zz}
\def\zzz#1#2{\omit}

\begin{document}


$\mymacro{abc}{def}$

$\mymacro{123456}{aaabbb}$

\end{document}

答案2

\documentclass{article}
\newcommand\mymacro[2]{%
  \process{\tmpA}{#1}%
  \process{\tmpB}{#2}%
  \begin{array}{\arwd}
  \tmpA\\\hline\tmpB
  \end{array}
}
\newcommand\process[2]{\def\arwd{}\def#1{}\processA#1#2\relax}
\makeatletter
\def\processA#1#2#3\relax{%
  \if\relax#1\relax\else\g@addto@macro#1{&}\fi
  \g@addto@macro#1{#2}%
  \g@addto@macro\arwd{c}%
  \ifx\relax#3\relax\else\processA#1#3\relax\fi
}
\makeatother
\begin{document}
$\mymacro{abc}{def}$

$\mymacro{12345}{67890}$
\end{document}

在此处输入图片描述

答案3

您可以执行多行,而不需要计算任何项目的长度。

\documentclass{article}
\usepackage{booktabs} % better rules

\ExplSyntaxOn

\NewDocumentCommand{\mymacro}{O{\\}m}
 {% #1 = separator, #2 = data
  \fukai_mymacro:nn { #1 } { #2 }
 }

\int_new:N \l__fukai_mymacro_length_int
\seq_new:N \l__fukai_mymacro_body_seq
\seq_new:N \l__fukai_mymacro_row_seq

\cs_new_protected:Nn \fukai_mymacro:nn
 {
  \seq_set_split:Nnn \l__fukai_mymacro_body_seq { #1 } { #2 }
  \int_zero:N \l__fukai_mymacro_length_int
  \seq_map_inline:Nn \l__fukai_mymacro_body_seq
   {
    \int_compare:nT { \l__fukai_mymacro_length_int < \tl_count:n { ##1 } }
     {
      \int_set:Nn \l__fukai_mymacro_length_int { \tl_count:n { ##1 } }
     }
   }
  \begin{array}{ * { \l__fukai_mymacro_length_int } { c } }
  \seq_map_indexed_function:NN \l__fukai_mymacro_body_seq \__fukai_mymacro_row:nn
  \end{array}
 }

\cs_new_protected:Nn \__fukai_mymacro_row:nn
 {% #1 is the index, #2 is the item
  \int_compare:nF { #1 = 1 } { \\ \midrule }
  \seq_set_split:Nnn \l__fukai_mymacro_row_seq { } { #2 }
  \seq_use:Nn \l__fukai_mymacro_row_seq { & }
 }

\ExplSyntaxOff

\begin{document}

\[
\mymacro{abc \\ def }
\]

\[
\mymacro{abcde \\ fg \\ uvw}
\]

\[
\mymacro[,]{ab,def}
\]

\end{document}

默认情况下,行分隔符为\\,但可以使用可选参数进行不同的设置。

参数在所选分隔符处拆分;然后计算每个项的长度以确定列数。接下来通过“从零”处拆分生成每一行。

在此处输入图片描述

如果您的所有表格都只有两行,那么您可以采取类似的方式。

\documentclass{article}
\usepackage{booktabs} % better rules

\ExplSyntaxOn

\NewDocumentCommand{\mymacro}{mm}
 {
  \fukai_mymacro:nn { #1 } { #2 }
 }

\seq_new:N \l__fukai_mymacro_row_seq

\cs_new_protected:Nn \fukai_mymacro:nn
 {
  \begin{array}
   {
    * { \int_max:nn { \tl_count:n { #1 } } { \tl_count:n { #2 } } } { c }
   }
  \seq_set_split:Nnn \l__fukai_mymacro_row_seq { } { #1 }
  \seq_use:Nn \l__fukai_mymacro_row_seq { & }
  \\ \midrule
  \seq_set_split:Nnn \l__fukai_mymacro_row_seq { } { #2 }
  \seq_use:Nn \l__fukai_mymacro_row_seq { & }
  \end{array}
 }

\ExplSyntaxOff

\begin{document}

\[
\mymacro{abc}{def}
\]

\[
\mymacro{abcde}{uvw}
\]

\[
\mymacro{ab}{def}
\]

\end{document}

在此处输入图片描述

答案4

以下 MWE 形成了一个完全可扩展的宏机制,其中外循环在形成数组行的未限定参数列表上进行迭代,并且对于数组的每一“行”,内循环在列条目列表(也是未限定参数列表)上进行迭代。

\makeatletter
%%-----------------------------------------------------------------------------
%% Check whether argument is empty:
%%.............................................................................
%% \UD@CheckWhetherNull{<Argument which is to be checked>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is empty>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is not empty>}%
%%
%% The gist of this macro comes from Robert R. Schneck's \ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
\newcommand\UD@CheckWhetherNull[1]{%
  \romannumeral\expandafter\@secondoftwo\string{\expandafter
  \@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
  \@secondoftwo\string}\expandafter\@firstoftwo\expandafter{\expandafter
  \@secondoftwo\string}\expandafter\UD@stopromannumeral\@secondoftwo}{%
  \expandafter\UD@stopromannumeral\@firstoftwo}%
}%
\@ifdefinable\UD@stopromannumeral{\chardef\UD@stopromannumeral=`\^^00}%
%%-----------------------------------------------------------------------------
\@ifdefinable\UD@loopovercolumentries{%
  \long\def\UD@loopovercolumentries#1#2#3#4\bizarre#5#6#7#8{%
    % #1 - if #2=\@firstoftwo, then 
    %       <needed amount of c detected with previous columns> minus <amount of column-entries processed in this loop so far>
    %      if #2=\@secondoftwo, then 
    %      <amount of c> by which <amount of c needed by this row> so far exceeds <needed amount of c detected with previous columns>
    % #2 - \firstoftwo/\secondoftwo - fork if c need to be removed/added from #1;
    %      when the loop teminates: fork if this column required more c than 
    %      previous columns
    % #3 - first column-entry not processed so far
    % #4 - remaining column-entries not processed so far
    % #5 - column-separator to prepend to row in this iteration
    % #6 - stuff to append to column-separator in next iteration
    % #7 - needed amount of c detected with previous columns 
    % #8 - rows and columns gathered so far
    \UD@CheckWhetherNull{#4}{#2{\UD@loopoverrowentries{#7}}{\UD@loopoverrowentries{#7#1}}{#8}}{%
      #2{\ifcat$#1$\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi}%
      {\@firstoftwo}%
      {\UD@loopovercolumentries{#1c}{\@secondoftwo}}%
      {\expandafter\UD@loopovercolumentries\expandafter{\@firstoftwo{}#1}{#2}}%
      #4\bizarre{#5#6}{}{#7}{#8#5#3}%
    }%
  }%
}%
\@ifdefinable\UD@loopoverrowentries{%
  \long\def\UD@loopoverrowentries#1#2#3#4\bizarre#5#6{%
    % #1 - needed amount of c detected so far 
    % #2 - rows and columns gathered so far
    % #3 - first row/first list of column-entries not processed so far
    % #4 - remaining rows/remaining lists of column-entries not processed so far
    % #5 - row-separator to prepend to row in this iteration
    % #6 - stuff to append to row-separator in next iteration
    \UD@CheckWhetherNull{#4}{%
      \ifcat$#1$\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
      {\UD@stopromannumeral}{\UD@stopromannumeral\begin{array}{#1}#2\end{array}}%
    }{%
      \UD@loopovercolumentries{#1}{\@firstoftwo}#3{{}{}}\bizarre{}{&}{#1}{#2#5}%
      #4\bizarre{#5#6}{}%
    }%
  }%
}%
\newcommand\mymacro[1]{%
  % \romannumeral-trickery, not to obtain roman numerals but to ensure
  % that the result can be obtained by triggering exactly two
  % expansion-steps:
  \romannumeral
  \expandafter\@firstoftwo\expandafter{\expandafter%
    \UD@stopromannumeral
    \romannumeral\UD@loopoverrowentries{}{}#1{{}{}}\bizarre{}{\\\hline}%
  }{}%
}%
%%-----------------------------------------------------------------------------
\makeatother

\documentclass{article}

\begin{document}

\[ \mymacro{{abc}{defghij}{kl}{mno}{pqr}} \]

\[ \mymacro{{ab}{cd}{ef}{gh}{ij}{kl}{mn}{op}{qr}} \]

\[ \mymacro{{abcdef}{gh}{ijk}{lmn}{op}{qr}} \]

\[ \mymacro{{{ab}{cd}{ef}}{gh}{ijk}{lmn}{op}{qr}} \]

\end{document}

在此处输入图片描述

相关内容