我想定义一个宏来轻松编写集合。例如:
\set{ 1, 2, 3, 4, 5 }
然后变成类似
\{ 1,\ 2,\ 3,\ 4,\ 5\, \} % this
\begin{Bmatrix}\, 1,\, 2,\, 3 ,\, 4,\, 5\, \end{Bmatrix} % or this
此外我还需要:
- 可以改变括号:例如 \set[p]{ 1, 2, 3 }
- 可以改变分隔符:例如用空格替换逗号
- 段落对齐时允许每个逗号后自动换行
目前我改编了我在这里找到的东西:
更改在 Latex 中输入矩阵的方式,结果得到了以下代码(针对宏\tset
):
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\tset}{ O{B} m }
{
\strategy_tset:nn { #1 } { #2 }
}
\seq_new:N \l_strategy_rows_seq
\seq_new:N \l_strategy_a_row_seq
\tl_new:N \l_strategy_matrix_tl
\cs_new_protected:Npn \strategy_tset:nn #1 #2
{
\tl_clear:N \l_strategy_matrix_tl
\seq_set_split:Nnn \l_strategy_rows_seq { ; } { #2 }
\seq_map_inline:Nn \l_strategy_rows_seq
{
\seq_set_split:Nnn \l_strategy_a_row_seq { , } { ##1 }
\tl_put_right:Nx \l_strategy_matrix_tl { \seq_use:Nn \l_strategy_a_row_seq { , } }
}
\begin{#1matrix}
\, \tl_use:N \l_strategy_matrix_tl \,
\end{#1matrix}
}
\ExplSyntaxOff
我认为这不太好。特别是换行功能不起作用。
答案1
以下是用于确定分隔符和定界符的基于键值的代码。换行符只能在第二项之后和倒数第二项之前使用。
\documentclass[twocolumn]{article}
\usepackage{amsmath}
\ExplSyntaxOn
\NewDocumentCommand{\tset}{O{}m}
{
\strategy_tset_main:nn { #1 } { #2 }
}
\seq_new:N \l__strategy_tset_items_seq
\str_new:N \l__strategy_tset_delim_str
\tl_new:N \l__strategy_tset_sep_tl
\tl_new:N \l__strategy_tset_last_tl
\keys_define:nn { strategy/tset }
{
B .code:n = \str_set:Nn \l__strategy_tset_delim_str { B },
p .code:n = \str_set:Nn \l__strategy_tset_delim_str { p },
b .code:n = \str_set:Nn \l__strategy_tset_delim_str { b },
comma .code:n = \tl_set:Nn \l__strategy_tset_sep_tl { , },
space .code:n = \tl_set:Nn \l__strategy_tset_sep_tl { \ },
}
\cs_new_protected:Nn \strategy_tset_main:nn
{
\group_begin:
\keys_set:nn { strategy/tset } { B, comma, #1 }
% left delimiter
\str_case:Vn \l__strategy_tset_delim_str
{
{B}{\{}
{p}{(}
{b}{[}
}
% items with separators
\tl_if_blank:nF { #2 }
{
\seq_set_from_clist:Nn \l__strategy_tset_items_seq { #2 }
\seq_pop_right:NN \l__strategy_tset_items_seq \l__strategy_tset_last_tl
\seq_map_indexed_inline:Nn \l__strategy_tset_items_seq
{
##2 % the item
\tl_use:N \l__strategy_tset_sep_tl % the separator
% add \linebreak[0] only after the second and before the last but one item
\int_compare:nT { 1 < ##1 < \seq_count:N \l__strategy_tset_items_seq }
{
\linebreak[0]
}
}
\tl_use:N \l__strategy_tset_last_tl % the last item
}
% right delimiter
\str_case:Vn \l__strategy_tset_delim_str
{
{B}{\}}
{p}{)}
{b}{]}
}
\group_end:
}
\ExplSyntaxOff
\begin{document}
$\tset{1,2,3,4}$
$\tset[space,b]{a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p}$
Some words words ww $\tset[space,b]{a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p}$
Some words words words $\tset[space,b]{a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p}$
Some words ww $\tset[p]{a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p}$
Some words words words words words www $\tset[comma,p]{a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p}$
$\tset{}$
$
\tset[p]{
1,
\tset[b]{
2,
3,
\tset[{B,space}]{
a,
b,
c
},
4
},
5
}
$
\end{document}
我不会增加逗号后的空格;如果你真的想要,可以使用类似
comma .code:n = \tl_set:Nn \l__strategy_tset_sep_tl { ,\; },
如您所见,嵌套是可以的,但如果嵌套中需要更多选项\tset
,则需要将它们括在括号中,如上一个示例所示。
检查参数是否为空,在这种情况下只打印分隔符。
答案2
这只是用来clist
映射逗号列表,然后用撤消最后的“逗号”间距\unskip
。
\documentclass{article}
\usepackage{amsmath}
\ExplSyntaxOn
\newcommand\set[2][\{]{
#1
\clist_map_inline:nn{#2}{##1\nolinebreak[2]\;}
\unskip\unpenalty
\ifx\{#1\}\else
\ifx(#1)\else
?\fi\fi}
\ExplSyntaxOff
\begin{document}
$\set{1,2,3}$ $\set[(]{1,2,3}$
some test text some test text some test text
$\set{a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z}$
\end{document}