我想创建一个宏“\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}