假设我想要生成一个 5x4 矩阵。一个好方法是编写以下命令:
\[
\begin{tikzpicture}
\matrix(m) [matrix of nodes, ampersand replacement=\&, row sep=1ex, column sep=1ex, nodes in empty cells, nodes={shape=rectangle,minimum height=3ex, anchor=center},] {
$A_{11}$ \& $A_{12}$ \& $A_{13}$ \& $A_{14}$ \\
$A_{21}$ \& $A_{22}$ \& $A_{23}$ \& $A_{24}$ \\
$A_{31}$ \& $A_{32}$ \& $A_{33}$ \& $A_{34}$ \\
$A_{41}$ \& $A_{42}$ \& $A_{43}$ \& $A_{44}$ \\
$A_{51}$ \& $A_{52}$ \& $A_{53}$ \& $A_{54}$ \\
};
\node[fit= (m-1-1.north west) (m-5-4.south east), left delimiter={[}, right delimiter={]},inner sep=1ex] {};
\end{tikzpicture}
\]
(我使用它,tikz
因为它允许我格式化单个矩阵元素并插入图形)。如果我必须填充 10x9 矩阵,这可能会变得相当累人。这个想法是编写一个包含三个输入的 NewDocumentCommand:表示矩阵的字母、行数和列数。使用expl3
我应该能够生成矩阵内容。然后我应该能够编写类似以下内容的内容:
\begin{tikzpicture}
\matrix(m) [matrix of nodes, ampersand replacement=\&, row sep=1ex, column sep=1ex, nodes in empty cells, nodes={shape=rectangle,minimum height=3ex, anchor=center},] {
\matrixcontents
};
\node[fit= (m-1-1.north west) (m-#2-#3.south east), left delimiter={[}, right delimiter={]},inner sep=1ex] {};
\end{tikzpicture}
其中\matrixcontents
包含
$A_{11}$ \& $A_{12}$ \& $A_{13}$ \& $A_{14}$ \\
$A_{21}$ \& $A_{22}$ \& $A_{23}$ \& $A_{24}$ \\
$A_{31}$ \& $A_{32}$ \& $A_{33}$ \& $A_{34}$ \\
$A_{41}$ \& $A_{42}$ \& $A_{43}$ \& $A_{44}$ \\
$A_{51}$ \& $A_{52}$ \& $A_{53}$ \& $A_{54}$ \\
和#2
,#3
分别是NewDocumentCommand的行数、列数参数(本例中#1
为字母A)。
我是一个绝对的初学者expl3
,所以我不知道如何生成\matrixcontents
。
答案1
您可以按照以下方式操作:
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{matrix,fit}
\ExplSyntaxOn
\NewDocumentCommand{\matrixcontents}{mmm}
{% #1 = symbol, #2 = number of rows, #3 = number of columns
\tl_clear:N \l_tmpa_tl
\int_step_inline:nn { #2 }
{% ##1 = row index
\int_step_inline:nn { #3 - 1 }
{% ####1 = column index
\tl_put_right:Nn \l_tmpa_tl { $#1\sb{##1####1}$ \& }
}
\tl_put_right:Nn \l_tmpa_tl { $#1\sb{##1#3}$ \\ }
}
\tl_use:N \l_tmpa_tl
}
\ExplSyntaxOff
\begin{document}
\[
\begin{tikzpicture}
\matrix(m) [
matrix of nodes,
ampersand replacement=\&,
row sep=1ex,
column sep=1ex,
nodes in empty cells,
nodes={
shape=rectangle,
minimum height=3ex,
anchor=center
},
]{
\matrixcontents{A}{5}{4}
};
\node[
fit= (m-1-1.north west) (m-5-4.south east),
left delimiter={[},
right delimiter={]},
inner sep=1ex
] {};
\end{tikzpicture}
\]
\end{document}
代码对行执行循环,并对每一行执行循环(行中的最后一个单元格是特殊的)。
更短一点:
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{matrix,fit}
\NewDocumentCommand{\symbolicmatrix}{O{}mmm}{%
% #1 = further options, #2 = symbol, #3 = number of rows, #4 = number of columns
\matrix(m) [
matrix of nodes,
ampersand replacement=\&,
row sep=1ex,
column sep=1ex,
nodes in empty cells,
nodes={
shape=rectangle,
minimum height=3ex,
anchor=center
},#1,
]{\matrixcontents{#2}{#3}{#4}};
\node[
fit= (m-1-1.north west) (m-#3-#4.south east),
left delimiter={[},
right delimiter={]},
inner sep=1ex
] {};
}
\ExplSyntaxOn
\NewDocumentCommand{\matrixcontents}{mmm}
{% #1 = symbol, #2 = number of rows, #3 = number of columns
\tl_clear:N \l_tmpa_tl
\int_step_inline:nn { #2 }
{% ##1 = row index
\int_step_inline:nn { #3 - 1 }
{% ####1 = column index
\tl_put_right:Nn \l_tmpa_tl { $#1\sb{##1####1}$ \& }
}
\tl_put_right:Nn \l_tmpa_tl { $#1\sb{##1#3}$ \\ }
}
\tl_use:N \l_tmpa_tl
}
\ExplSyntaxOff
\begin{document}
\[
\begin{tikzpicture}
\symbolicmatrix{A}{5}{4}
\end{tikzpicture}
\]
\end{document}
该\symbolicmatrix
命令有一个前导可选参数,可以为\matrix
命令提供更多选项。
例如
\[
\begin{tikzpicture}
\symbolicmatrix[row sep=2ex,column sep=2ex]{A}{5}{4}
\end{tikzpicture}
\]
会产生
答案2
供参考,该包nicematrix
提供了生成矩阵的命令,其中每个单元位于 TikZ 节点中(它不是tikz-matrix
)。
\documentclass{article}
\usepackage{nicematrix,tikz}
\begin{document}
$\bAutoNiceMatrix[name=A]{5-4}{A_{\arabic{iRow},\arabic{jCol}}}$
\begin{tikzpicture}[remember picture, overlay]
\draw [<-] (A-5-2) -- ++ (0,-5mm) node [below] {$x$} ;
\end{tikzpicture}
\end{document}
答案3
这与@egreg的答案类似,但使用可扩展代码构建矩阵主体,结果应该是更快的代码(但我没有进行基准测试)。此外,环境也tikzpicture
包含在宏中(如果您不想要它,您可以将其删除)。
我希望这些注释足以解释代码。
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{matrix, fit}
\ExplSyntaxOn
\int_new:N \l__ted_matrix_cols_int
\tl_new:N \l__ted_matrix_variable_tl
\cs_new:Npn \__ted_matrix_row:n #1
{
% after we built a row we need to remove the leading \exp_not:N \& from the
% first cell
\exp_last_unbraced:Ne \use_none:nn
{
% \prg_replicate:nn needs two steps of expansion
% we use it instead of an \int_map_... because there is no \int_map_...
% that allows us to expandably forward additional arguments (#1)
\exp_args:No \use_ii_i:on
{ \prg_replicate:nn \l__ted_matrix_cols_int \__ted_matrix_cell:nnN }
{ \__ted_matrix_cell:nnN 1 {#1} }
% the \use_none:nn ends the \__ted_matrix_cell:nnN loop
\use_none:nn
}
\exp_not:N \\
}
\cs_generate_variant:Nn \use_ii_i:nn { o }
% simple loop to return each cell
\cs_new:Npn \__ted_matrix_cell:nnN #1#2#3
{
% will be wrapped in two e-expansion contexts, inner one is from the row,
% outer one is from building the entire body
% $, #1, #2, and \sb don't need protection against further expansion.
\exp_not:n { \exp_not:N \& $ \exp_not:V \l__ted_matrix_variable_tl \sb { #2#1 } $ }
\exp_args:Ne #3 { \int_eval:n { #1 + 1 } } {#2}
}
\NewDocumentCommand \tmatrix { O{} m m m }
{
\begin{tikzpicture}
\tl_set:Nn \l__ted_matrix_variable_tl {#2}
% we store #4-1 because one is hardcoded by the way we start the loop to
% build each cell of a row.
\int_set:Nn \l__ted_matrix_cols_int { #4 - 1 }
\exp_args:Nne \use:n
{
\matrix(m) [matrix~of~nodes, ampersand~replacement=\&,
row~sep=1ex, column~sep=1ex, nodes~in~empty~cells,
nodes={shape=rectangle,minimum~height=3ex, anchor=center}, #1]
}
{ \int_step_function:nN {#3} \__ted_matrix_row:n }
;
\node[fit= (m-1-1.north~west) (m-#3-#4.south~east), left~delimiter={[},
right~delimiter={]},inner~sep=1ex]
{};
\end{tikzpicture}
}
\ExplSyntaxOff
\begin{document}
\tmatrix{A}{5}{4}
\end{document}
结果: