![来自列表的排序和压缩输出](https://linux22.com/image/337364/%E6%9D%A5%E8%87%AA%E5%88%97%E8%A1%A8%E7%9A%84%E6%8E%92%E5%BA%8F%E5%92%8C%E5%8E%8B%E7%BC%A9%E8%BE%93%E5%87%BA.png)
我有一个包含内容的 clist {9.8,5.1,10.1b,1.3,1.4,5,5.1.1,8a,9.7,9.9,10.1a,10.1c,1.2,8b,8c}
。如何使用 expl3 从中生成排序和压缩的输出,如下所示:
1.2--1.4、5、5.1.1、8a--8c、9.7--9.9 和 10.1a--10.1c
这是一个简单的例子:
\documentclass{article}
\usepackage{expl3}
\begin{document}
\sortandcompress{9.8,5.1,10.1b,1.3,1.4,5,5.1.1,8b,9.7,9.9,
10.1a,10.1c,1.2,8c,8a}
\end{document}
答案1
第一个版本,压缩现在可以使用,使用l3regex
功能。
有两个基本困难:
1.) 将条目拆分为数字部分(如 a24.345345.34
和 a)和字母部分tail
--> 用于\regex_extract_all:Nnn
此。2.) 使用合理的匹配“算法”\seq_sort:Nn
基本思想是将类似的内容转换8.5.3.d
为 8.534 since
d`,即普通拉丁字母中的第 4 个字符。
然而,这非常棘手,因为后续的数字像.534
都非常大——不使用 are 会导致数字进位到前导数字。
对范围进行分级和压缩也有点尴尬。
更新:先前版本使用了l3sort
包 - 该包被视为已弃用并且其功能已被吸收expl3
。
\documentclass{article}
\usepackage{l3regex}
\ExplSyntaxOn
\seq_new:N \l_item_rounded_seq
\seq_new:N \l_sort_abundance_seq
\seq_new:N \l_alpha_extract_seq
\seq_new:N \l_sort_seq
\seq_new:N \g_sortandcompress_seq
\fp_new:N \l_sort_varone_fp
\fp_new:N \l_sort_vartwo_fp
\cs_generate_variant:Nn \seq_set_split:Nnn {Nnx}
\cs_generate_variant:Nn \int_from_alph:n {V}
\cs_generate_variant:Nn \regex_extract_all:nnN {nxN}
\cs_generate_variant:Nn \regex_split:nnN {nxN}
\newcommand{\maptosortable}[2]{%
\regex_split:nnN { [a-z] } { #1 } \l_tmpb_seq
\regex_extract_all:nnN { [^0-9.] } { #1 } \l_alpha_extract_seq
\seq_set_split:Nnx \l_tmpa_seq {.} { \seq_item:Nn \l_tmpb_seq {1}}
\fp_zero:N #2
\fp_set:Nn \l_tmpb_fp {1.0}
\int_set:Nn \l_tmpa_int {0}
\fp_set:Nn \l_tmpa_fp {1.0}
\seq_map_inline:Nn \l_tmpa_seq {%
\tl_set:Nx \l_tmpa_tl {##1}
\int_incr:N \l_tmpa_int
\int_compare:nNnTF { \l_tmpa_int } = {1} {%
\int_set:Nn \l_tmpb_int {0}
}{
\int_add:Nn \l_tmpb_int {\tl_count:N \l_tmpa_tl}
}
\fp_set:Nn \l_tmpa_fp {\fp_eval:n {0.1 ^ {\l_tmpb_int}}}
\fp_add:Nn #2 { ##1 * \l_tmpa_fp}
}
% Now convert the possibly trailing alpha character
\int_compare:nNnT {\seq_count:N \l_alpha_extract_seq } > {0} {%
\tl_set:Nx \l_tmpa_tl {\seq_item:Nn \l_alpha_extract_seq {1}}
\int_set:Nn \l_tmpa_int {\int_from_alph:V { \l_tmpa_tl}}
\tl_set:NV \l_tmpa_tl {\l_tmpa_int}
\int_add:Nn \l_tmpb_int {\tl_count:N \l_tmpa_tl}% How many characters does the converted alpha need? -> power of ...
\fp_set:Nn \l_tmpa_fp {\fp_eval:n {0.1 ^ {\l_tmpb_int}}}
\fp_add:Nn #2 { \l_tmpa_int * \l_tmpa_fp }
}
}
\newcommand{\sortthis}[1]{%
\seq_set_from_clist:Nn \l_sort_seq {#1}%
\seq_sort:Nn \l_sort_seq {%
\maptosortable{##1}{\l_sort_varone_fp}
\maptosortable{##2}{\l_sort_vartwo_fp}
\fp_compare:nNnTF {\l_sort_varone_fp} > { \l_sort_vartwo_fp }
{ \sort_reversed:}
{ \sort_ordered:}
}
%\seq_use:Nn \l_sort_seq {,\par}
}
\newcommand{\sortandcompress}[1]{%
\sortthis{#1}%
\seq_gclear:N \g_sortandcompress_seq
\seq_clear:N \l_item_rounded_seq
\seq_map_inline:Nn \l_sort_seq {%
\maptosortable{##1}{\l_sort_varone_fp}%
\seq_put_right:Nx \l_item_rounded_seq {\fp_eval:n {floor (\l_sort_varone_fp , 0)}} % Round to the smaller integer
}
\seq_set_eq:NN \l_sort_abundance_seq \l_item_rounded_seq
\seq_remove_duplicates:N \l_sort_abundance_seq
\seq_clear:N \l_tmpb_seq
\seq_clear:N \l_tmpa_seq
\seq_map_inline:Nn \l_sort_abundance_seq {%
\int_zero:N \l_tmpa_int
\int_zero:N \l_tmpb_int
\seq_map_inline:Nn \l_item_rounded_seq {%
\int_compare:nNnT { ##1 } = { ####1 } { \int_incr:N \l_tmpb_int }
}
\seq_map_inline:Nn \l_item_rounded_seq {%
\int_incr:N \l_tmpa_int
\int_compare:nNnT { ##1 } = { ####1 } { \seq_map_break: }
}
\seq_put_right:NV \l_tmpa_seq {\l_tmpa_int} % store the current start index to \l_tmpa_seq
\seq_put_right:NV \l_tmpb_seq {\l_tmpb_int} % store the number of elements to \l_tmpb_seq
}
% Let's determine the real entries now
\int_zero:N \l_tmpa_int
\seq_map_inline:Nn \l_sort_abundance_seq {%
\int_incr:N \l_tmpa_int
\int_set:Nn \l_tmpb_int {\seq_item:Nn \l_tmpb_seq{ \l_tmpa_int} }
\int_compare:nNnTF { \seq_item:Nn \l_tmpb_seq{ \l_tmpa_int} } = {1} {%
\seq_gput_right:Nx \g_sortandcompress_seq {\seq_item:Nn \l_sort_seq {\seq_item:Nn \l_tmpa_seq {\l_tmpa_int}}}
}{%
% Calculate the stop index
\int_set:Nn \l_tmpb_int {\seq_item:Nn \l_tmpa_seq {\l_tmpa_int} + \seq_item:Nn \l_tmpb_seq {\l_tmpa_int} - 1 }
\seq_gput_right:Nx \g_sortandcompress_seq {\seq_item:Nn \l_sort_seq {\seq_item:Nn \l_tmpa_seq {\l_tmpa_int}} -- \seq_item:Nn \l_sort_seq {\l_tmpb_int}}
}
}
\seq_use:Nn \g_sortandcompress_seq {\par}
}
\ExplSyntaxOff
\begin{document}
\sortandcompress{9.8,5.1,10.1b,1.3,1.4,7.8,5,100.234b,5.1.1,8b,9.7,9.9,10.1a,10.1c,100.467q,1.2,8b,8a}
\end{document}
我不认为这会一直有效。诸如2.2.a
或1.a.5
等条目将会失败。