我有一个 tikz 矩阵,我想按从上到下到从下到上的顺序重新排列行
\matrix
{
a & b & c\\
d & e & f\\
g & h & i\\
}
到
\matrix
{
g & h & i\\
d & e & f\\
a & b & c\\
}
当然,对于简单的情况,我可以手动完成,但我有很多矩阵可能会改变。我想要一些重新排序宏。行尾分隔符是 \,所以这可能相当容易。
答案1
矩阵元素的任意排列
如果您想要置换矩阵条目,可以按如下方式进行。这是一个有效的原理证明。您定义一个矩阵,然后通过以下方式保存它
\matrix[matrix of nodes,save cells=A]
{
a & b & c\\
d & e & f\\
g & h & i\\
};
其中A
用作标识符(如果您有多个矩阵)。可以使用以下方法将该矩阵重新转换为置换形式
\matrix[xshift=3cm,matrix of nodes,declare function={mati(\i,\j)=4-\i;
matj(\i,\j)=\j;},reorder cells=A]
{
& & \\
& & \\
& & \\
};
此处的函数mati(\i,\j)
和定义了行索引和列索引matj(\i,\j)
的映射。在本例中,它只是恢复了行的顺序。\i
\j
\documentclass[tikz,border=3mm]{standalone}
\usetikzlibrary{matrix}
\makeatletter
\tikzset{save cells/.style={cells={nodes={execute at begin
node={\ifcsname matrixcellbox#1-\the\pgfmatrixcurrentrow-\the\pgfmatrixcurrentcolumn\endcsname%
\else%
\expandafter\newbox\csname matrixcellbox#1-\the\pgfmatrixcurrentrow-\the\pgfmatrixcurrentcolumn\endcsname%
\fi%
\expandafter\expandafter\global\setbox\csname matrixcellbox#1-\the\pgfmatrixcurrentrow-\the\pgfmatrixcurrentcolumn\endcsname=\hbox\bgroup},
execute at end
node={\egroup%
\expandafter\copy\csname matrixcellbox#1-\the\pgfmatrixcurrentrow-\the\pgfmatrixcurrentcolumn\endcsname%
}}}},
reorder cells/.style={nodes in empty cells,
cells={nodes={execute at begin
node={
\setbox0=\hbox\bgroup},
execute at end
node={\egroup%
\pgfmathtruncatemacro{\myi}{mati(\the\pgfmatrixcurrentrow,\the\pgfmatrixcurrentcolumn)}%
\pgfmathtruncatemacro{\myj}{matj(\the\pgfmatrixcurrentrow,\the\pgfmatrixcurrentcolumn)}%
%\typeout{(\the\pgfmatrixcurrentrow,\the\pgfmatrixcurrentcolumn)->(\myi,\myj)}%
\expandafter\copy\csname matrixcellbox#1-\myi-\myj\endcsname%
}}}}}
\makeatother
\begin{document}
\begin{tikzpicture}
\matrix[matrix of nodes,save cells=A]
{
a & b & c\\
d & e & f\\
g & h & i\\
};
\matrix[xshift=3cm,matrix of nodes,declare function={mati(\i,\j)=4-\i;
matj(\i,\j)=\j;},reorder cells=A]
{
& & \\
& & \\
& & \\
};
\end{tikzpicture}
\end{document}
以更复杂的样式定义为代价,可以通过使用以下方法避免用户输入空矩阵:这些惯例当然,也可以将节点数学化。此示例中的映射也稍微复杂一些:
\documentclass[tikz,border=3mm]{standalone}
\usepackage{etoolbox}
\usetikzlibrary{matrix}
\newcommand{\CreateEmptyMatrix}[3]{% based on https://tex.stackexchange.com/a/60400
\xdef#3{}%
\foreach \j in {1,...,#1}{
\foreach \i in {1,...,\the\numexpr#2-1} {%
\begingroup\edef\x{\endgroup
\noexpand\gappto\noexpand#3{ {} \&}}\x
}%
\gappto#3{\\}%
}
}
\makeatletter
\tikzset{save cells/.style={cells={nodes={execute at begin
node={\ifcsname matrixcellbox#1-\the\pgfmatrixcurrentrow-\the\pgfmatrixcurrentcolumn\endcsname%
\else%
\expandafter\newbox\csname matrixcellbox#1-\the\pgfmatrixcurrentrow-\the\pgfmatrixcurrentcolumn\endcsname%
\fi%
\expandafter\expandafter\global\setbox\csname matrixcellbox#1-\the\pgfmatrixcurrentrow-\the\pgfmatrixcurrentcolumn\endcsname=\hbox\bgroup},
execute at end
node={\egroup%
\expandafter\copy\csname matrixcellbox#1-\the\pgfmatrixcurrentrow-\the\pgfmatrixcurrentcolumn\endcsname%
}}},
execute at end matrix={%
\expandafter\xdef\csname matrix@rows@#1\endcsname{\the\pgfmatrixcurrentrow}%
\expandafter\xdef\csname matrix@colss@#1\endcsname{\the\pgfmatrixcurrentcolumn}%
}},
save math cells/.style={cells={nodes={execute at begin
node={\ifcsname matrixcellbox#1-\the\pgfmatrixcurrentrow-\the\pgfmatrixcurrentcolumn\endcsname%
\else%
\expandafter\newbox\csname matrixcellbox#1-\the\pgfmatrixcurrentrow-\the\pgfmatrixcurrentcolumn\endcsname%
\fi%
\expandafter\expandafter\global\setbox\csname matrixcellbox#1-\the\pgfmatrixcurrentrow-\the\pgfmatrixcurrentcolumn\endcsname=\hbox\bgroup$},
execute at end
node={$\egroup%
\expandafter\copy\csname matrixcellbox#1-\the\pgfmatrixcurrentrow-\the\pgfmatrixcurrentcolumn\endcsname%
}}},
execute at end matrix={%
\expandafter\xdef\csname matrix@rows@#1\endcsname{\the\pgfmatrixcurrentrow}%
\expandafter\xdef\csname matrix@cols@#1\endcsname{\the\pgfmatrixcurrentcolumn}%
}},
reorder cells/.style={/utils/exec=%
\edef\myrows{\csname matrix@rows@#1\endcsname}%
\edef\mycols{\csname matrix@cols@#1\endcsname}%
\CreateEmptyMatrix{\myrows}{\mycols}{\myemptymatrix},
ampersand replacement=\&,
node contents=\myemptymatrix,
nodes in empty cells,
cells={nodes={execute at begin
node={
\setbox0=\hbox\bgroup},
execute at end
node={\egroup%
\edef\myrows{\csname matrix@rows@#1\endcsname}%
\edef\mycols{\csname matrix@cols@#1\endcsname}%
\pgfmathtruncatemacro{\myi}{max(1,min(\myrows,mati(\the\pgfmatrixcurrentrow,\the\pgfmatrixcurrentcolumn)))}%
\pgfmathtruncatemacro{\myj}{max(1,min(\mycols,matj(\the\pgfmatrixcurrentrow,\the\pgfmatrixcurrentcolumn)))}%
%\typeout{(\the\pgfmatrixcurrentrow,\the\pgfmatrixcurrentcolumn)->(\myi,\myj)}%
\expandafter\copy\csname matrixcellbox#1-\myi-\myj\endcsname%
}}}}}
\makeatother
\begin{document}
\begin{tikzpicture}
\matrix[matrix of nodes,save math cells=A]
{
a & b & c\\
d & e & f\\
g & h & i\\
};
\matrix[xshift=3cm,matrix of nodes,
declare function={mati(\i,\j)=4-\i;
matj(\i,\j)=4-\j;},reorder cells=A]
{
};
\end{tikzpicture}
\end{document}
当然,人们可以抑制第一个矩阵的输出,例如,将其放入我们从未使用过的盒子中。
旧答案:拨负数即可达到此效果row sep
。
\documentclass[tikz,border=3mm]{standalone}
\usetikzlibrary{matrix}
\tikzset{swap rows/.style={row sep=-3em,yshift=1em}}
\begin{document}
\begin{tikzpicture}
\matrix[matrix of math nodes]
{
a & b & c\\
d & e & f\\
g & h & i\\
};
\matrix[xshift=3cm,matrix of math nodes,swap rows]
{
a & b & c\\
d & e & f\\
g & h & i\\
};
\end{tikzpicture}
\end{document}