来自列表的排序和压缩输出

来自列表的排序和压缩输出

我有一个包含内容的 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 sinced`,即普通拉丁字母中的第 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.a1.a.5等条目将会失败。

在此处输入图片描述

相关内容