我正在使用基于以下定义的宏一些建议这里可以自动创建表。
例如
\newcommand{\clearrows}{\let\matrixcontent\empty}
\newcommand{\actionsrow}[3]{%
\foreach \i in #3 {%
\pgfmathparse{#1[\i-1]}
\let\c\pgfmathresult
\pgfmathparse{#2[\i-1]}
\let\s\pgfmathresult
\begingroup\edef\x{\endgroup
\noexpand\gappto\noexpand\matrixcontent{\noexpand\node[\s]{\c}; \&}}\x
}%
\gappto\matrixcontent{\\}%
}
让我只需几行代码就能轻松创建所需的表格。例如,
\newcommand{\rowhv}[1]{
\actionsrow{{"$e$","$h$","$v$","$hv$"}}{{{"fill=gray!3"},{"fill=gray!33"},{"fill=gray!67"},{"fill=gray!100"}}}{#1} }
\clearrows
\rowhv{{1,2,3,4}} \rowhv{{2,1,4,3}} \rowhv{{3,4,1,2}} \rowhv{{4,3,2,1}}
\begin{tikzpicture}
\matrix[ampersand replacement=\&,nodes={minimum size=7mm}]{\matrixcontent};
\end{tikzpicture}
生产
这看起来可能不是什么了不起的成就,但我需要建立相当大的表格,而且要建立很多表格,所以这些宏至关重要。
我需要能够在单元格中放置任意内容,范围从任意格式(例如\textsf{..}
)到导入的图像(例如使用\includegraphics
)或我定义的其他宏来绘制节点内容。但上面的代码仅适用于纯文本的单元格内容。如果我在第一个参数中的项目中提供纯文本以外的任何内容(\actionsrow
用于\c
循环中),我会收到错误,
\reserved@a 的参数有一个额外的}。
尽管此类内容对于节点而言完全有效。我怀疑我的(窃取的)宏解析方式出了问题\c
,但我甚至不知道从哪里开始追踪。
我如何修改我的\actionsrow
宏以便我可以将任意 LaTeX 指定为我的节点的内容?
\documentclass[]{article}
\usepackage{etoolbox}
\usepackage{tikz}
\usetikzlibrary{matrix}
\begin{document}
% See -- https://tex.stackexchange.com/a/47649/7844
\newcommand{\clearrows}{\let\matrixcontent\empty}
\newcommand{\actionsrow}[3]{%
\foreach \i in #3 {%
\pgfmathparse{#1[\i-1]} % See -- https://tex.stackexchange.com/a/56838/7844; note \let vs \def
\let\c\pgfmathresult
\pgfmathparse{#2[\i-1]}
\let\s\pgfmathresult
\begingroup\edef\x{\endgroup
\noexpand\gappto\noexpand\matrixcontent{\noexpand\node[\s]{\c}; \&}}\x
}%
\gappto\matrixcontent{\\}%
}
% This works fine
\newcommand{\rowhv}[1]{
\actionsrow{{"$e$","$h$","$v$","$hv$"}}{{{"fill=gray!3"},{"fill=gray!33"},{"fill=gray!67"},{"fill=gray!100"}}}{#1} }
\clearrows
\rowhv{{1,2,3,4}} \rowhv{{2,1,4,3}} \rowhv{{3,4,1,2}} \rowhv{{4,3,2,1}}
\begin{center}
\begin{tikzpicture}
\matrix[ampersand replacement=\&,nodes={minimum size=7mm}]{\matrixcontent};
\end{tikzpicture}
\end{center}
% Here, arbitrary specifications work for the nodes, if done manually
\begin{center}
\begin{tikzpicture}
\matrix [nodes={minimum size=7mm}]
{
\node[fill=gray!3]{\texttt{e}}; & \node[fill=gray!33]{\color{red}$h$}; & \node[fill=gray!67]{$v$}; & \node[fill=gray!100]{$hv$}; \\
\node[fill=gray!33]{\color{red}$h$}; & \node[fill=gray!3]{\texttt{e}}; & \node[fill=gray!100]{$hv$}; & \node[fill=gray!67]{$v$}; \\
\node[fill=gray!67]{$v$}; & \node[fill=gray!100]{$hv$}; & \node[fill=gray!3]{\texttt{e}}; & \node[fill=gray!33]{\color{red}$h$}; \\
\node[fill=gray!100]{$hv$}; & \node[fill=gray!67]{$v$}; & \node[fill=gray!33]{\color{red}$h$}; & \node[fill=gray!3]{\texttt{e}}; \\
};
\end{tikzpicture}
\end{center}
% But this fails
\renewcommand{\rowhv}[1]{
\actionsrow{{"\texttt{e}","\color{red}$h$","$v$","$hv$"}}{{{"fill=gray!3"},{"fill=gray!33"},{"fill=gray!67"},{"fill=gray!100"}}}{#1} }
\clearrows
\rowhv{{1,2,3,4}} \rowhv{{2,1,4,3}} \rowhv{{3,4,1,2}} \rowhv{{4,3,2,1}}
\begin{center}
\begin{tikzpicture}
\matrix[ampersand replacement=\&,nodes={minimum size=7mm}]{\matrixcontent};
\end{tikzpicture}
\end{center}
\end{document}
答案1
您有两个问题,都与有关\edef
。第二个问题实际上是与您的有关,因为任何进入\edef
的宏都会被扩展并造成混乱。第一个问题是与有关,因为根据手册,数学表达式中的所有内容都会完全展开,因此,您需要对应该的内容进行额外的保护#1
\c
\x
\pgfmathparse
不是需要扩展。我发现有两种方法可以解决这个问题:
手动将
\unexpanded
每个项目放在数组的周围#1
,并将其放在数组的\expandonce
前面(因此它被展开,但其内容没有展开)。这很麻烦,但可以解决问题。\c
\edef
在继续执行当前的主体之前,先用 进行初步循环以
\foreach
放入这些s 。由于让双引号与此很好地交互会很麻烦,我建议您为其第一个参数制作语法,\unexpanded
\actionsrow
{$a$, $\mathbf{b}$, \includegraphics{c.pdf}, ...}
没有引号,并添加\foreach
和\unexpanded
引号。另外,不要忘记\expandonce\c
,\edef
和前面一样。
以下是我实施选项 2 的方法:
\newcommand{\actionsrow}[3]{%
%%%
% NEW STUFF
%%%
\let\comma=\empty
\let\b=\empty
\foreach \a in {#1} {%
\xappto\b{\comma"\noexpand\unexpanded{\expandonce\a}"}%
\gdef\comma{,}%
}%
\foreach \i in #3 {%
%%% CHANGED #1 -> \b
\pgfmathparse{{\b}[\i-1]}%
\let\c\pgfmathresult
\pgfmathparse{#2[\i-1]}%
\let\s\pgfmathresult
\begingroup\edef\x{\endgroup
%%% ADDED \expandonce\c
\noexpand\gappto\noexpand\matrixcontent{\noexpand\node[\s]{\expandonce\c}; \&}}\x
}%
\gappto\matrixcontent{\\}%
}
\newcommand{\rowhv}[1]{
\actionsrow
%%% NEW SYNTAX: first arg is a pure CSV list
{$\mathbf{e}$,$h$,$v$,$hv$}
{{{"fill=gray!3"},{"fill=gray!33"},{"fill=gray!67"},{"fill=gray!100"}}}
{#1}%
}