使用 spalign 包对矩阵进行垂直对齐

使用 spalign 包对矩阵进行垂直对齐

我正在使用spalign用于排版矩阵和方程组的包。

基本上,它只是允许您在输入矩阵和基于数组的类似内容时使用空格(或逗号)和分号而不是&and 。\\

我想垂直对齐一些矩阵或方程组,就好像它们的基线是第一行(或方程)的基线而不是垂直居中,就像在环境中array使用该[t]选项一样。

MWE 是:

\documentclass[12pt]{report}
\usepackage{spalign}
\usepackage{amsmath}

\begin{document}
Normal matrix vertically aligned so that it is vertically centered:

\[
  A=\spalignmat{1 2 3;4 5 6;7 8 9}
\]

The same matrix using amsmath environments:
\[
  A=\begin{pmatrix}
      1&2&3\\
      4&5&6\\
      7&8&9
  \end{pmatrix}
\]

I would like it to vertically align with baseline at the baseline of the first row, like you can do with an array:

\[
  A=\begin{array}[t]{ccc}
      1&2&3\\
      4&5&6\\
      7&8&9
  \end{array}
\]

A system using spalign:
$\spalignsys{2x + 3y = 1;x - y = 10}$
\end{document}

在此处输入图片描述

我希望能够像数组对齐一样对齐矩阵(和系统)。该spalign软件包有工具可以创建您自己的快捷命令(所以我知道如何创建使用spalign快捷方式的顶部对齐数组环境),但我不知道如何让它自动处理分隔符和列对齐。同样,我可以使用数组环境来排版系统,但最好能像在 中一样自动处理变量的数量等spalign

如果无法在中完成spalign,那么使用环境的解决方案pmatrix将是次佳选择(但是,正如您在示例中看到的那样,数组和分隔符之间的间距略有不同,所以对我来说并不理想,因为它看起来与我的其他矩阵不同)。

谢谢你的帮助!

答案1

这不受支持spalign

这是一个不同的实现。

\documentclass[12pt]{report}
\usepackage{xparse}
\usepackage{amsmath}
\usepackage{delarray}

\ExplSyntaxOn
\NewDocumentCommand{\extraalign}{O{}m}
 {
  \group_begin:
  \keys_set:nn { extraalign } { #1 }
  \extraalign_make:n { #2 }
  \group_end:
 }

\NewDocumentCommand{\extraalignset}{m}
 {
  \keys_set:nn { extraalign } { #1 }
 }

\tl_new:N \l__extraalign_cols_tl
\tl_new:N \l__extraalign_row_tl
\seq_new:N \l__extraalign_rows_in_seq
\seq_new:N \l__extraalign_rows_out_seq
\seq_new:N \l__extraalign_row_seq
\int_new:N \l__extraalign_cols_int

\keys_define:nn { extraalign }
 {
  h .code:n = \tl_set:Nn \l__extraalign_cols_tl { *{\l__extraalign_cols_int}{#1} },
  h .initial:n = c,
  v .tl_set:N = \l__extraalign_vertical_tl,
  v .initial:n = c,
  p .code:n = \tl_set:Nn \l__extraalign_cols_tl { #1 },
  l .tl_set:N = \l__extraalign_left_tl,
  l .initial:n = (,
  r .tl_set:N = \l__extraalign_right_tl,
  r .initial:n = ),
 }

\cs_new_protected:Nn \extraalign_make:n
 {
  \__extraalign_body:n { #1 }
  \__extraalign_preamble:VVVV
   \l__extraalign_vertical_tl % vertical alignment
   \l__extraalign_left_tl     % left delimiter
   \l__extraalign_right_tl    % right delimiter
   \l__extraalign_cols_tl     % column spec
  % deliver the matrix
  \seq_use:Nn \l__extraalign_rows_out_seq { \\ }
  \end{array}
 }

\cs_new_protected:Nn \__extraalign_preamble:nnnn
 {
  \begin{array}[#1]#2{@{}#4@{}}#3
 }
\cs_generate_variant:Nn \__extraalign_preamble:nnnn { VVVV }

\cs_new_protected:Nn \__extraalign_body:n
 {
  \seq_set_split:Nnn \l__extraalign_rows_in_seq { ; } { #1 }
  \seq_clear:N \l__extraalign_rows_out_seq
  \seq_map_variable:NNn \l__extraalign_rows_in_seq \l__extraalign_row_tl
   {
    \__extraalign_makerow:V \l__extraalign_row_tl
   }
 }

\cs_new_protected:Nn \__extraalign_makerow:n
 {
  \seq_set_split:Nnn \__extraalign_row_seq { ~ } { #1 }
  \int_compare:nT { \l__extraalign_cols_int = 0 }
   {
    \int_set:Nn \l__extraalign_cols_int { \seq_count:N \__extraalign_row_seq }
   }
  \seq_put_right:Nx \l__extraalign_rows_out_seq
   { \seq_use:Nn \__extraalign_row_seq { & } }
 }
\cs_generate_variant:Nn \__extraalign_makerow:n { V }

\ExplSyntaxOff


\begin{document}

\begin{gather*}
  A=\begin{pmatrix}1 & 2 & 3 \\ 4 & 5 & 6 \\ 7 & 8 & 9\end{pmatrix}
\quad
  A=\extraalign{1 2 3;4 5 6;7 8 9}
\\
  A=\extraalign[v=t]{1 2 3;4 5 6;7 8 9}
\quad
  A=\extraalign[p=rcl,v=t]{-1 2 3;4 5 66;700 8 9000}
\\
  A=\extraalign[l=\{,r=.,h=l]{aaaa ; bbb ; c}
\end{gather*}

\end{document}

可选参数\extraalign包含选项的键值列表

  • h对于列的一般格式(默认c),列数根据需要
  • p对于特殊前导,指定所有列
  • v对于垂直对齐,tcb默认c
  • l表示左分隔符(默认();.不使用分隔符
  • r表示右分隔符(默认));.表示无分隔符

如果您想要更改默认值,请使用\extraalignset您想要的值。例如,如果您这样做

\extraalignset{ l = [, r = ] }

所有矩阵(在当前范围内或在序言中完成的全局范围内)都将使用括号,除非本地被撤销。

在此处输入图片描述

为了完整性,下面介绍如何执行增广矩阵。

\extraalignset{l=[,r=]}

\begin{gather*}
  A=\extraalign[p=cccc|cc]{1 2 3 4 5 6;4 5 6 7 8 9;7 8 9 1 2 3}
  \quad
  A=\extraalign[p=cccc|cc,v=t]{1 2 3 4 5 6;4 5 6 7 8 9;7 8 9 1 2 3}
\\
  A=\extraalign[p=ccc|ccc]{1 2 3 4 5 6;4 5 6 7 8 9;7 8 9 1 2 3}
  \quad
  A=\extraalign[p=ccc|ccc,v=t]{1 2 3 4 5 6;4 5 6 7 8 9;7 8 9 1 2 3}
\end{gather*}

在此处输入图片描述

答案2

\documentclass{article}
\usepackage{tabstackengine,scalerel}
\TABstackMath
\setstacktabbedgap{1ex}
\strutlongstacks{T}
\begin{document}
\[
A = \tabbedLongunderstack{1&2&3\\4&5&6\\7&8&9}
\]
\[
A = \scaleleftright[1.5ex]{\Biggl(}
   {\tabbedLongunderstack{1&2&3\\4&5&6\\7&8&9}}{\Biggr)}
\]
\[
\savestack\mysystem{\setstacktabbedgap{0pt}%
  \tabbedCenterstack[r]{2x +& 3y =& 1\\x -& y =& 10}}
\renewcommand\stackalignment{r}
\stackunder[10pt]
{$A = \tabbedLongunderstack{1&2&3\\4&5&6\\7&8&9}$}
{A system using tabstackengine: $\biggl\{\mysystem$}
\]
\end{document}

在此处输入图片描述

答案3

我很感谢其他的回答。这个问题困扰了我一段时间,而且由于这个问题很久都没有得到解答(我认为它太具体了,除了我之外显然没有人需要这样做),我找到了一种通过修补命令来实现的方法spalign。为了防止其他人想知道如何做到这一点,我会在这里发布我的答案。

我不得不深入研究spalign一下现有代码。矩阵array按预期使用 s 构建,所以我最初想到只需用 替换\begin{align}\begin{align}[t]然而,这会产生一个问题,即分隔符也位于顶行的中心:

顶部对齐

为了解决这个问题,我delarray按照这个建议使用了回答(正如egreg回答这个问题时再次建议的那样)。

但是,这需要在现有的 代码中进行更为复杂的查找和替换spalign,因为该包中的宏将分隔符放在环境之外array(不使用 时通常如此)delarray。无论如何,我有点痴迷于解决这个问题,并通过xpatch反复试验解决了它。我认为这有点混乱(部分原因是*中 s 的处理方式spalign),但以下代码会创建几个spalign环境的副本,与它们的顶行对齐,所有可选参数和带星号的版本均完好无损:

\documentclass[12pt]{report}
\usepackage{amsmath}
\usepackage[delims={[}{]},sysdelims={.}{.}]{spalign} %set to square brackets on matrices and no delimiters on systems
\usepackage{letltxmacro}
\usepackage{delarray}
\usepackage{xpatch}

\makeatletter

\let\tmat=\spalignmat
\let\tmatx=\spalignmat@x
\LetLtxMacro\tmatstar\spalignmat@star
\xpatchcmd{\tmat}{\spalignmat@x}{\tmatx}{}{}
\xpatchcmd{\tmatx}{\spalignmat@star}{\tmatstar}{}{}
\xpatchcmd{\tmatstar}{\spalign@maybedelim}{\spalignenv}{}{}
\xpatchcmd{\tmatstar}{\begin{array}{\spalign@repeated}}%
    {\begin{array}[t]\ifspalign@star\else\spalign@leftdelim\fi%
    {@{\spalignmatdelimskip}\spalign@repeated @{\spalignmatdelimskip}}%
    \ifspalign@star\else\spalign@rightdelim\fi}{}{}
\xpatchcmd{\tmatstar}{{\hskip-\arraycolsep\spalignmatdelimskip}}{}{}{}
\providecommand{\dtmat}[2][r]{{\detm \tmat[#1]{#2}}}

\let\tamatn=\spalignaugmatn
\let\tamatnx=\spalignaugmatn@x
\LetLtxMacro\tamatnstar\spalignaugmatn@star
\xpatchcmd{\tamatn}{\spalignaugmatn@x}{\tamatnx}{}{}
\xpatchcmd{\tamatnx}{\spalignaugmatn@star}{\tamatnstar}{}{}
\xpatchcmd{\tamatnstar}{\spalign@maybedelim}{\spalignenv}{}{}
\xpatchcmd{\tamatnstar}{\begin{array}{\spalign@repeated@one|\spalign@repeated@two}}%
    {\begin{array}[t]\ifspalign@star\else\spalign@leftdelim\fi%
    {@{\spalignmatdelimskip}\spalign@repeated@one|\spalign@repeated@two @{\spalignmatdelimskip}}\ifspalign@star\else\spalign@rightdelim\fi}{}{}
\xpatchcmd{\tamatnstar}{{\hskip-\arraycolsep\spalignmatdelimskip}}{}{}{}

\providecommand{\tamat}[1][r]{%
    \tamatn[#1]{1}%
    }%

\let\tamath=\spalignaugmathalf
\let\tamathx=\spalignaugmathalf@x
\LetLtxMacro\tamathstar\spalignaugmathalf@star
\xpatchcmd{\tamath}{\spalignaugmathalf@x}{\tamathx}{}{}
\xpatchcmd{\tamathx}{\spalignaugmathalf@star}{\tamathstar}{}{}
\xpatchcmd{\tamathstar}{\spalign@maybedelim}{\spalignenv}{}{}
\xpatchcmd{\tamathstar}{\begin{array}{\spalign@repeated@one|\spalign@repeated@two}}%
    {\begin{array}[t]\ifspalign@star\else\spalign@leftdelim\fi%
    {@{\spalignmatdelimskip}\spalign@repeated@one|\spalign@repeated@two @{\spalignmatdelimskip}}\ifspalign@star\else\spalign@rightdelim\fi}{}{}
\xpatchcmd{\tamathstar}{{\hskip-\arraycolsep\spalignmatdelimskip}}{}{}{}

\let\tsys=\spalignsys
\let\tsysx=\spalignsys@x
\let\tsysstar=\spalignsys@star
\xpatchcmd{\tsys}{\spalignsys@x}{\tsysx}{}{}
\xpatchcmd{\tsysx}{\spalignsys@star}{\tsysstar}{}{}
\xpatchcmd{\tsysstar}{\vcenter}{\vtop}{}{}

\makeatother

\begin{document}

\[
    A=\spalignmat{1 2 3;4 5 6;7 8 9}. \quad A=\tmat{1 2 3;4 5 6;7 8 9}.
\]

\[
    A=\spalignaugmat{1 2 3;4 5 6;7 8 9}. \quad A=\tamat{1 2 3;4 5 6;7 8 9}.
\]

\[
    A=\spalignaugmatn{2}{1 2 3 4 5 6;4 5 6 7 8 9;7 8 9 1 2 3}. \quad A=\tamatn{2}{1 2 3 4 5 6;4 5 6 7 8 9;7 8 9 1 2 3}.
\]

\[
    A=\spalignaugmathalf{1 2 3 4 5 6;4 5 6 7 8 9;7 8 9 1 2 3}. \quad A=\tamath{1 2 3 4 5 6;4 5 6 7 8 9;7 8 9 1 2 3}.
\]

System of equations:
$\spalignsys{2x + 3y = 1;x - y = 10}$.\quad
Top aligned:
$\tsys{2x + 3y = 1;x - y = 10}$.

\end{document}

其结果为: 顶部对齐 spalign

这些就是我所需要的,所以我只修补了它们。其他的也可以类似地做。

ed*版本省略了分隔符,矩阵采用可选参数来指定列对齐。这两个功能仍可像原始版本一样工作spalign

也许重新定义我想要的宏比使用 更简单\xpatchcmd,但我发现这样做很有启发性。我xpatch以前从未使用过,在第一次尝试中学到了很多东西。

我无法让方程组的分隔符顶部对齐,因为spalign使用的halign是该系统而不是array环境。对我来说,这不是问题,因为我所教的书无论如何都不在系统上使用分隔符,而且我想使用一致的符号。

答案4

{bNiceMatrix}的环境为受启发的语法nicematrix提供了一个键,并为顶行对齐提供了一个键,如。light-syntaxspalignt{array}

因此,可以直接编写一个命令来\MyMatrix执行您希望的操作。

\documentclass[12pt]{article}
\usepackage{nicematrix}

\NewDocumentCommand { \MyMatrix } { m }
  { 
    \begin{bNiceMatrix}[t,light-syntax]
    #1
    \end{bNiceMatrix}
  }

\begin{document}
\[ A=\MyMatrix{1 2 3;4 5 6;7 8 9} \]
\end{document}

您需要多次编译(因为nicematrix在后台使用 PGF/Tikz 节点)。

上述代码的输出

相关内容