基本问题
我正在尝试生成一个命令\m
序列
- 从数学模式中调用,带有一个参数
list
- 用和(分别)“替换” 中的所有和
,
。;
list
&
\\
- 创建一个
pmatrix
以 1 & 2 为内容的输出
例如,代码
\[
\m{a,b;c,d}\m{x;y}
\]
应扩展为相当于以下内容:
\[
\begin{pmatrix}a&b \\ c&d\end{pmatrix}\begin{pmatrix}x \\ y\end{pmatrix}
\]
在花了比我应该花的更多的时间之后,我想出了以下解决问题的部分方法xstring
:
\def\foo#1{
\StrSubstitute{#1}{,}{&}[\result]
\verbtocs{\bslashes}|\\|
\expandarg
\StrSubstitute{\result}{;}{ \bslashes }[\result]
}
\begin{document}
% Fairly complicated matrix input
\foo{a,b,c;d,e_{f,g},h;i,j_{1,e^n},k}
\[
\begin{pmatrix}
\result
\end{pmatrix}
\]
\end{document}
这接近我所期望的,但我还没有想出一种方法来用作\foo
辅助函数来\m
获得我想要的。我\m
在想在序言中定义
\def\m#1{
\foo{#1}
\begin{pmatrix}
\result
\end{pmatrix}
}
可以工作,但即使在数学模式下调用一些简单的东西\m{a}
也会产生错误。看起来数学模式试图解析定义\m
而不是完全\m
展开,但我对此工作原理的理解太有限,不知道如何修复我的代码。
有没有办法修改 的定义\m
并\foo
使其按我的要求执行?我能否以某种方式退出 定义中的数学模式\m
以避免这些错误?
答案1
这是一种老式的方法,使用带有分隔参数的宏。
\documentclass{article}
\usepackage{amsmath} % for pmatrix environment
\newtoks\asqltoks
\makeatletter
\def\gobtilundef #1\undef {}
\def\matlabmatrix #1{\asqltoks{\begin{pmatrix}}\@asqlA #1;\undef;}
% \def\@asqlA #1;{\gobtilundef #1\@asqlE\undef\@asqlR #1,\undef,}
% update: simplified to ->
\def\@asqlA #1;{\@asqlR #1,\undef,}
\def\@asqlB #1;{\gobtilundef #1\@asqlE\undef
\asqltoks\expandafter{\the\asqltoks \\}\@asqlR #1,\undef,}
\def\@asqlE\undef #1\undef,\undef,{%
\asqltoks\expandafter{\the\asqltoks\end{pmatrix}}\the\asqltoks }
\def\@asqlR #1,{\asqltoks\expandafter{\the\asqltoks #1}\@asqlS }
\def\@asqlS #1,{\gobtilundef #1\@asqlZ\undef
\asqltoks\expandafter{\the\asqltoks }\@asqlS }
\def\@asqlZ #1\@asqlS {\@asqlB }
\makeatother
\begin{document}
$\matlabmatrix {m}$
$\matlabmatrix {m,n}$
$\matlabmatrix {m,n;p,q}$
$\matlabmatrix {a,b,c;d,e_{f,g},h;i,j_{1,e^n},k}$
\end{document}
答案2
以下是具有功能的实现expl3
:
\documentclass{article}
\usepackage{xparse,amsmath}
\ExplSyntaxOn
\NewDocumentCommand{\matlabmatrix}{m}
{
\asql_matlab_matrix:n { #1 }
}
\seq_new:N \l_asql_rows_seq
\seq_new:N \l_asql_one_row_seq
\tl_new:N \l_asql_matrix_tl
\cs_new_protected:Npn \asql_matlab_matrix:n #1
{
% clear the token list variable containing the final data
\tl_clear:N \l_asql_matrix_tl
% split the argument at the semicolon
\seq_set_split:Nnn \l_asql_rows_seq { ; } { #1 }
% build one row at a time
\seq_map_inline:Nn \l_asql_rows_seq
{
\__asql_build_row:n { ##1 }
}
% print the matrix
\begin{pmatrix}
\tl_use:N \l_asql_matrix_tl
\end{pmatrix}
}
% the inner function
\cs_new_protected:Npn \__asql_build_row:n #1
{
% split the input at commas
\seq_set_split:Nnn \l_asql_one_row_seq { , } { #1 }
% add the row to the token list variable
% items are separated by &
\tl_put_right:Nx \l_asql_matrix_tl
{ \seq_use:Nnnn \l_asql_one_row_seq { & } { & } { & } }
% add also the \\ row terminator
\tl_put_right:Nn \l_asql_matrix_tl { \\ }
}
\ExplSyntaxOff
\begin{document}
\begin{gather*}
\matlabmatrix{a,b;c,d}\matlabmatrix{x;y} \\
\matlabmatrix{a,b,c;d,e_{f,g},h;i,j_{1,e^n},k}
\end{gather*}
\end{document}
这很简单:我们首先用分号分割参数;然后用逗号分割每个项目,并逐行构建矩阵的内容。最后将内容插入和之间\begin{pmatrix}
进行\end{pmatrix}
打印。
答案3
此代码应该可以完成您想要的操作:
\documentclass{article}
\usepackage{xstring,amsmath}
\newcommand*\mmm[1]{%
\begingroup\expandarg
\StrSubstitute{\noexpand#1},&[\result]%
\StrSubstitute\result{\noexpand;}{\noexpand\\}[\result]%
\begin{pmatrix}\result\end{pmatrix}\endgroup
}
\begin{document}
\[\mmm{a,b,c;d,e_{f,g},h;i,j_{1,e^n},k}\]
\[\mmm{a}\]
\end{document}
答案4
显然,在最后一行之后pmatrix
保留了一个附加行,而无需添加额外的行(与通常的数学环境不同)。但是必须删除附加行,这是通过 完成的。\\
&
\@gobblesecondoftwo
;
我还提供了一个解决方案,它使用 TeX 的分隔参数在s 和s处分割参数,
。
代码
\documentclass{article}
\usepackage{amsmath}
% xparse solution
\usepackage{xparse}
\makeatletter
\def\@gobblethirdofthree#1#2#3{#1#2}
\def\@gobblesecondoftwo#1#2{#1}
\NewDocumentCommand\foo{>{\SplitList;}m}{
\begin{pmatrix} \ProcessList{#1}\@foo \end{pmatrix}
}
\NewDocumentCommand\@foo{>{\SplitList,}m}{
\expandafter\expandafter\expandafter\@gobblesecondoftwo
\ProcessList{#1}\@@foo \\
}
\def\@@foo#1{}
% plain delimited parameters
\newcommand*{\fooo}[1]{%
\begin{pmatrix}\foo@split@semi#1;\foo@@@split@semi\foo@@split@semi\end{pmatrix}
}
\def\foo@split@semi#1;#2\foo@@split@semi{%
\foo@split@comma#1,\foo@@@split@comma\foo@@split@comma
\ifx\foo@@@split@semi#2\expandafter\@gobble\else
\expandafter\@firstofone
\fi{\\\foo@split@semi#2\foo@@split@semi}%
}
\def\foo@split@comma#1,#2\foo@@split@comma{%
#1
\ifx\foo@@@split@comma#2\expandafter\@gobble\else
\expandafter\@firstofone
\fi{&\foo@split@comma#2\foo@@split@comma}%
}
\makeatother
\begin{document}
$\foo{a,b,c;d,e_{f,g},h;i,j_{1,e^n},k}$
$\foo{m}$
$\fooo{a,b,c;d,e_{f,g},h;i,j_{1,e^n},k}$
$\fooo{m}$
\end{document}