我想发出一个命令\exactseq
,例如,
\exactseq{A,f,B,g,C}
对应于
\xymatrix{A \ar[r]^{f} & B \ar[r]^{g} & C}
并且这适用于任意长度的输入,而不仅仅是某些固定长度。准确地说,我想输入一个列表,当 n 为奇数时,将列表的第 n 个元素作为 xymatrix 中的条目,当 n 为偶数时,将其作为箭头。
编辑:正如 Werner 在下面询问的那样,我通常会有长度超过一个字符的条目和箭头,并且可能不是纯文本,例如\Omega
,或f_{i}
,或\mathbb{Z}
。上面给出的简单示例仅用于说明目的。
我一直试图使用etoolbox
包的列表命令来实现这一点;作为初次尝试(甚至没有定义\exactseq
),我尝试
\documentclass[11pt]{article}
\usepackage{amsmath,amssymb,amsthm,amsfonts}
\usepackage{etoolbox}
\usepackage[all]{xy}
\begin{document}
\newcounter{obfun}
\setcounter{obfun}{0}
\renewcommand*{\do}[1]{\ifnumodd{\value{obfun}}{\ar[r]^{#1} &}{#1}\stepcounter{obfun}}
\[\xymatrix{\docsvlist{A,f,B,g,C}}\]
\end{document}
但这会产生大量错误,主要与缺失或放错有关\cr
(恐怕我不明白这是什么意思)。我尝试\expandafter
在 之前放置\xymatrix
,但这没有帮助。
我如何创建命令来进行书写正合序列更加自动化?当然,它不必使用etoolbox
,或者xy
就此而言。
编辑:egreg 的答案确实有效,但我对引入的所有这些新命令并不熟悉,expl3
所以我真的不明白它是如何工作的,而且如果以后我想修改它,我也不知道该如何着手。因此,我想请求一个“低技术”解决方案(也许使用更常见或某种意义上“基本”的软件包),或者只是其他解决方案(如果您看到的话)。如果似乎没有其他解决方案,我会接受 egreg 的答案。
也许有办法使用这个TikZ代码这也适用于更一般的对象和箭头数组吗?
答案1
以下是一个使用的方法expl3
。
\documentclass{article}
\usepackage[all,cmtip]{xy}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\exactseq}{ O{+0pt} m }
{
\exactseq_main:nn { #1 } { #2 }
}
\int_new:N \l__exactseq_place_int
\tl_new:N \l__exactseq_seq_tl
\cs_new_protected:Npn \exactseq_main:nn #1 #2
{
\tl_clear:N \l__exactseq_seq_tl
\int_zero:N \l__exactseq_place_int
\clist_map_inline:nn { #2 } { \__exactseq_process:n { ##1 } }
\xymatrix@C#1 { \l__exactseq_seq_tl }
}
\cs_new_protected:Npn \__exactseq_process:n #1
{
\int_if_even:nTF { \l__exactseq_place_int }
{
\int_compare:nT { \l__exactseq_place_int > 0 }
{ \tl_put_right:Nn \l__exactseq_seq_tl { & } }
\tl_put_right:Nn \l__exactseq_seq_tl { #1 }
}
{
\tl_put_right:Nn \l__exactseq_seq_tl { \ar[r]^{#1} }
}
\int_incr:N \l__exactseq_place_int
}
\ExplSyntaxOff
\begin{document}
$\exactseq{A,f,B,g,C}$
$\exactseq[+1em]{A,f,B,g,C,h,D}$
\end{document}
该命令\exactseq
有一个可选参数,用于改变列间距(\xymatrix@C+1em{...}
在示例中)。
我们处理列表,使用一个整数变量跟踪我们所处的位置,从 0 开始。我们将第一个对象添加到标记列表变量中,然后在偶数正位置(对应于除最左边的对象以外的对象)添加&
该对象。在奇数位置我们添加\ar[r]^{f}
(这里f
表示箭头标签)。
最后,我们发布\xymatrix@C<optional argument>{<contents of the token list>}
。
版本带有etoolbox
,详细说明您的示例。
\documentclass[11pt]{article}
\usepackage{amsmath,amssymb,amsthm,amsfonts}
\usepackage{etoolbox}
\usepackage[all]{xy}
\newcounter{obfun}
\newcommand{\exactseq}[2][+0pt]{%
\setcounter{obfun}{0}%
\def\storedsofar{}%
\forcsvlist{\appendtoseq}{#2}%
\xymatrix@C#1{\storedsofar}
}
\newcommand{\appendtoseq}[1]{%
\ifnumodd{\value{obfun}}
{\appto\storedsofar{\ar[r]^{#1} &}}
{\appto\storedsofar{#1}}
\stepcounter{obfun}%
}
\begin{document}
\[\exactseq{A,f,B,g,C}\]
\[\exactseq[+1em]{A,f,B,g,C}\]
\end{document}
此方法与使用 的方法非常相似expl3
;\storedsofar
代替\l__exactseq_seq_tl
,我们将项目一个接一个地添加。 该\forcsvlist
命令是 的模拟\clist_map_inline:nn
,因为它对参数进行循环,并使用 处理它们\appendtoseq
。 在expl3
上述版本中,列表中的每个项目都由执行 操作的辅助函数处理\appendtoseq
。
在 中执行所有操作的问题在于,\xymatrix
这会在内部使用\halign
(就像 一样tabular
),因此使用是危险的(也是导致大量错误的原因)。因此,最好的策略是将所有材料收集到辅助存储位置(或)&
中,然后将这个材料提供给。\l__exactseq_seq_tl
\storedsofar
\xymatrix