使用 l3 中的宏对不同表示形式的数字列表进行排序

使用 l3 中的宏对不同表示形式的数字列表进行排序

我想使用宏对具有不同表示形式的数字进行排序。例如 3.5%、0.321、17/5、... 如果可能的话,排序列表的输出应该再次采用相同的格式,或者 17/5 应该采用 \frac{17}{5} 格式。

不幸的是,我的知识不够,所以我想寻求帮助和建议。

通过我之前的尝试,数字已经可以排序了。但目前还不能以不同的格式排序。使用 xint,我也可以得到表示形式:17/5 -> \frac{17}{5},但之后我就无法再对列表进行排序了。

在此处输入图片描述

\documentclass{article}
\usepackage{siunitx,xfp,xintexpr}
\sisetup{group-separator={\,},output-decimal-marker={,}}

\ExplSyntaxOn
\NewDocumentCommand { \Sortiere } { s m }
 {
   \clist_set:Nn  \l_sort_clist  { #2 }
   \clist_sort:Nn \l_sort_clist
   {
   \IfBooleanTF{#1}
     { \fp_compare:nNnTF { \fp_eval:n{ ##1 } } < { \fp_eval:n{ ##2 } }
                            { \sort_return_swapped: }
                            { \sort_return_same: }
     }
     { \fp_compare:nNnTF { \fp_eval:n{ ##1 } } > { \fp_eval:n{ ##2 } }
                            { \sort_return_swapped: }
                            { \sort_return_same: }
     }
   }
%  \seq_new:N \l__thomas_A_seq
%  \seq_clear:N \l__thomas_A_seq
%  \clist_map_inline:nn { #2 }
%   { \seq_put_right:Nx \l__thomas_A_seq
%     { \ensuremath { \xintSignedFrac{\xintIrr { \fp_eval:n { ##1 } } } } }
%   }
%   \seq_use:Nn \l__thomas_A_seq {;\,}
   \{\l_sort_clist\}
 }
\ExplSyntaxOff



\begin{document}

\Sortiere{1,12,9/5,7.12,-3,-5,2,7,11}

\end{document} 

答案1

我认为你应该将值和表示分开。你可以使用一个简单的整数序列进行排序,然后将此排序应用于其他序列(我使用了水果和数量,因为我认为如果序列包含不同的东西,更容易理解):

\documentclass{article}
\usepackage{xparse}

\begin{document}
\ExplSyntaxOn
\seq_new:N \l_th_fruit_seq
\seq_new:N \l_th_fruit_sorted_seq
\seq_set_from_clist:Nn\l_th_fruit_seq {apples,pears,pineapples,bananas}

\seq_new:N \l_th_fruitqty_seq
\seq_new:N \l_th_fruitqty_sorted_seq
\seq_set_from_clist:Nn\l_th_fruitqty_seq  {10,5,20,2}

\int_zero:N\l_tmpa_int
\seq_clear:N\l_tmpa_seq
\seq_map_inline:Nn\l_th_fruit_seq % a temporary seq with 1,2,3,4 for the sorting
 {
  \int_incr:N\l_tmpa_int
  \seq_put_right:NV\l_tmpa_seq {\l_tmpa_int}
 }

\seq_sort:Nn \l_tmpa_seq %sort over the quantity
 {
  \int_compare:nNnTF { \seq_item:Nn\l_th_fruitqty_seq {#1} } > { \seq_item:Nn\l_th_fruitqty_seq {#2} }
   { \sort_return_swapped: }
   { \sort_return_same:    }
 }

\seq_map_inline:Nn \l_tmpa_seq  %apply the sorting to the seqs:
{
 \seq_put_right:Nx \l_th_fruit_sorted_seq    { \seq_item:Nn   \l_th_fruit_seq{#1} }
 \seq_put_right:Nx \l_th_fruitqty_sorted_seq { \seq_item:Nn \l_th_fruitqty_seq{#1}}
}

Sorted~fruits:~\seq_use:Nn\l_th_fruit_sorted_seq {,~}
\par
Quantities:~\seq_use:Nn \l_th_fruitqty_sorted_seq {,~}

\ExplSyntaxOff


\end{document} 

在此处输入图片描述

答案2

我可以提出以下从您自己的回答中得出的观点,我放弃了一两个选项,因为无论如何我不知道 xparse 语法。

我对 expl3 的了解有限,因此可能存在一些不太理想的地方。

想法如下:目前只有 xint 可以处理精确的分数(超过一定大小),只有 fpeval 知道对数等。因此,只需解析输入,如果有符号/,则假设这是某个分数,并通过解析它\xintthexpr以允许某个表达式(下面我的示例需要);如果没有,则/通过解析数字输入fpeval

然后使用 xint 例程进行所有比较测试,因为它们将接受的输出作为输入\fpeval

我们保留原始输入以供最终打印,但(在当前版本的代码中)/如上所述的任何内容都会触发计算\xinttheexpr

当然,这种方法会中断ln(2)/2,但对于了解 xparse 和 expl3 和 regex 的人来说(不是我)触发它并不难\fpeval

简而言之,用进行最大限度的计算,\fpeval但用进行所有的比较,xint因为它允许任意大的分数。

为了简化,我删除了所有检测是否\num可以用于格式化输出的代码,但同样,很容易添加(我也不了解 siunitx !)

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage[ngerman]{babel}
\usepackage{siunitx,xfp,xintexpr}
\sisetup{group-separator={\,},output-decimal-marker={,}}

\ExplSyntaxOn


\clist_new:N \l_T_printnumbers_clist
\tl_new:N \l_T_parsedinput_tl

\NewDocumentCommand{ \Sortiere }{ O{} t> t! m }
 {
  \group_begin:
  \keys_set:nn { thomas/Sortiere } { #1 }
  \tl_clear:N \l_T_parsedinput_tl
  \int_zero:N \l_tmpa_int
  \clist_map_inline:nn { #4 }
       { 
          \tl_set:Nn \l_tmpa_tl { ##1 }
% FIXING THE REGEX FOR \%
          \regex_replace_all:nnN { \c{\%} } { /100 } \l_tmpa_tl
% (debugging) \show\l_tmpa_tl
          \regex_replace_all:nnN { \c{ln} } { ln } \l_tmpa_tl
% (debugging) \show\l_tmpa_tl
         \regex_replace_all:nnN { \c{sqrt} } { sqrt } \l_tmpa_tl
          % notice here ##1 is tested so a /100 from a \% will be still be fp_evaluated
          \regex_match:nnTF { .*/.* } { ##1 } 
             {
               \tl_set:Nx \l_tmpa_tl { \xinttheexpr ##1 \relax }
               \tl_set:Nx \l_tmpa_tl { 
                                       { \exp_not:V \l_tmpa_tl } 
                                       { \exp_not:N \xintSignedFrac 
                                                    { \exp_not:V \l_tmpa_tl }
                                       }
                                     }
             }
             {
               \tl_set:Nx \l_tmpa_tl { 
                                       { \fp_eval:n { \l_tmpa_tl } }
                                       { \exp_not:n { ##1 } } 
                                     }
             }
          \tl_put_right:Nx \l_T_parsedinput_tl { { \exp_not:V \l_tmpa_tl } }
        }
   {
  %\show\l_T_parsedinput_tl
  \tl_sort:Nn \l_T_parsedinput_tl
   {
     \IfBooleanTF{#2}
       { \xintifLt { \use_i:nn ##1 } { \use_i:nn ##2 } }
       { \xintifGt { \use_i:nn ##1 } { \use_i:nn ##2 } }
         { \sort_return_swapped: }
         { \sort_return_same: }
   }
  \clist_clear:N \l_T_printnumbers_clist
  \tl_map_inline:Nn \l_T_parsedinput_tl
    { 
        \clist_put_right:Nn \l_T_printnumbers_clist { \use_ii:nn ##1 }
    }
   \IfBooleanTF{#2}
    { \clist_use:Nnnn \l_T_printnumbers_clist { \,\ensuremath { \geq }\, }{ \,\ensuremath { \geq }\, }{ \,\ensuremath { \geq }\, } }
    { \clist_use:Nnnn \l_T_printnumbers_clist { \,\ensuremath { \leq }\, }{ \,\ensuremath { \leq }\, }{ \,\ensuremath { \leq }\, } }
    }
  \group_end:
 }

\keys_define:nn { thomas/Sortiere }
 {
  unsort .bool_set:N = \l__T_Sortiere_unsort_bool,   
  unsort .initial:n  = false,                              % Starteinstellung 
  unsort .default:n  = true,                               % 
  round  .int_set:N = \l__thomas_sortiere_round_int,       % IGNORED
  round  .initial:n = 4,
 }
\ExplSyntaxOff

\sisetup{exponent-product=\cdot}

\begin{document}

\[  \Sortiere{10, 101/10, 10.015, 3*34} \]

\[ \Sortiere{2^4, 4^2, 3^2, 5^{0.5}, 13, 25-1, \ln(17)} \]

\[ \Sortiere>!{2^4, 4^2, 3^2, 5^{0.5}, 13, 25-1, \ln(17)} \]

\[ \Sortiere{1.5\%,1,12,9/5,7.12,-3e1,-5,2,\sqrt{8}} \]

\[ \Sortiere{46296296/123456789, 370370371/987654320, (370370371/987654320 + 46296296/123456789)/2}\]

\end{document}

在此处输入图片描述

答案3

这是我最后尝试的。

在此处输入图片描述

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage[ngerman]{babel}
\usepackage{siunitx,xfp,xintexpr}
\sisetup{group-separator={\,},output-decimal-marker={,}}

\ExplSyntaxOn
\NewDocumentCommand{ \Sortiere }{ O{} t> t! m }
 {
  \group_begin:
  \keys_set:nn { thomas/Sortiere } { #1 }
  \clist_set:Nn \l_T_numberlist_clist { #4 }
  \clist_set:Nn \l_T_number_unsort_clist { #4 }
   \tl_replace_all:Nnn \l_T_number_unsort_clist { \% } { /100 }
    \regex_replace_all:nnN { \c{ln} } { ln } \l_T_number_unsort_clist
   \bool_if:NTF \l__T_Sortiere_unsort_bool
   {
     \clist_clear:N \l_T_printnumbers_unsort_clist
     \clist_map_inline:Nn \l_T_number_unsort_clist
       { \clist_put_right:Nn \l_T_printnumbers_unsort_clist { \ensuremath { ##1 } } }
       \ensuremath {
          \regex_replace_all:nnN { /100 } { \c{num}\cB\{ \1\cE\}\c{,}\c{\%} } \l_T_printnumbers_unsort_clist
          \regex_replace_all:nnN { ln } { \c{ln} } \l_T_printnumbers_unsort_clist
          \regex_replace_all:nnN { [+-]?\d+/[+-]?\d+ } { \c{xintSignedFrac} \cB\{ \0\cE\} } \l_T_printnumbers_unsort_clist
          \regex_replace_all:nnN { [+-]?\d+e[+-]?\d+ } { \c{num} \cB\{ \0\cE\} } \l_T_printnumbers_unsort_clist
          \regex_replace_all:nnN { \. } { , } \l_T_printnumbers_unsort_clist
          \regex_replace_all:nnN { (sqrt)(\{[+-]?\d+\}) } { \c{sqrt} \cB\{ \2\cE\} } \l_T_printnumbers_unsort_clist   
      \left\{ \clist_use:Nnnn \l_T_printnumbers_unsort_clist { ;\, }{ ;\, }{ ;\, } \right\}
   }
   }
   {
  \tl_replace_all:Nnn \l_T_numberlist_clist { \% } { /100 }
  \regex_replace_all:nnN { \c{ln} } { ln } \l_T_numberlist_clist
  \clist_sort:Nn \l_T_numberlist_clist
   {
     \IfBooleanTF{#2}
       { \fp_compare:nTF { ##1 < ##2 } }
       { \fp_compare:nTF { ##1 > ##2 } }
         { \sort_return_swapped: }
         { \sort_return_same: }
   }
  \clist_clear:N \l_T_printnumbers_clist
  \clist_map_inline:Nn \l_T_numberlist_clist
    { \IfBooleanTF{#3}
       { \clist_put_right:Nn \l_T_printnumbers_clist { \ensuremath { ##1 } } }
       { \clist_put_right:Nn \l_T_printnumbers_clist { \ensuremath { \xintSignedFrac{ \xintIrr { \xinttheexpr round ( \fp_eval:n { ##1 } ,\l__thomas_sortiere_round_int ) \relax } } } } }
    }
   \IfBooleanTF{#3}{ 
                     \regex_replace_all:nnN { /100 } { \c{num}\cB\{ \1\cE\}\c{,}\c{\%} } \l_T_printnumbers_clist
                     \regex_replace_all:nnN { ln } { \c{ln} } \l_T_printnumbers_clist
                     \regex_replace_all:nnN { [+-]?\d+/[+-]?\d+ } { \c{xintSignedFrac} \cB\{ \0\cE\} } \l_T_printnumbers_clist
                     \regex_replace_all:nnN { [+-]?\d+e[+-]?\d+ } { \c{num} \cB\{ \0\cE\} } \l_T_printnumbers_clist
                     \regex_replace_all:nnN { \. } { , } \l_T_printnumbers_clist
                     \regex_replace_all:nnN { (sqrt)(\{[+-]?\d+\}) } { \c{sqrt} \cB\{ \2\cE\} } \l_T_printnumbers_clist
                   } 
                   { }
   \IfBooleanTF{#2}
    { \clist_use:Nnnn \l_T_printnumbers_clist { \,\ensuremath { \geq }\, }{ \,\ensuremath { \geq }\, }{ \,\ensuremath { \geq }\, } }
    { \clist_use:Nnnn \l_T_printnumbers_clist { \,\ensuremath { \leq }\, }{ \,\ensuremath { \leq }\, }{ \,\ensuremath { \leq }\, } }
    }
  \group_end:
 }
  \clist_new:N \l_T_printnumbers_clist
  \clist_new:N \l_T_numberlist_clist
  \clist_new:N \l_T_number_unsort_clist
  \clist_new:N \l_T_printnumbers_unsort_clist

\keys_define:nn { thomas/Sortiere }
 {
  unsort .bool_set:N = \l__T_Sortiere_unsort_bool,   
  unsort .initial:n  = false,                              % Starteinstellung 
  unsort .default:n  = true,                               % 
  round  .int_set:N = \l__thomas_sortiere_round_int,
  round  .initial:n = 4,
 }
\ExplSyntaxOff

\sisetup{exponent-product=\cdot}

\begin{document}

\[ \Sortiere[unsort]>{2^4, 4^2, 3^2, 5^{0.5}, 13, 25-1, ln(17)} \]

\[ \Sortiere>{2^4, 4^2, 3^2, 5^{0.5}, 13, 25-1, ln(17)} \]

\[ \Sortiere[round=12]>{2^4, 4^2, 3^2, 5^{0.5}, 13, 25-1, \ln(17)} \]

\[ \Sortiere>!{2^4, 4^2, 3^2, 5^{0.5}, 13, 25-1, \ln(17)} \]

\[ \Sortiere{1.5\%,1,12,9/5,7.12,-3e1,-5,2,sqrt{8}} \]

\[ \Sortiere[unsort]!{1.5\%,1,12,-11/5,7.12,-3e1,-5,2,sqrt{8}} \]

\end{document} 

相关内容