如何按排版长度对一组字符串进行排序

如何按排版长度对一组字符串进行排序

我希望能够提供一组字符串(带格式),并按最终排版长度对它们进行排序。在我的特定情况下,最短的优先。(示例使用希望普遍可用的任意字体)注意:结果将用作 tikz 节点的文本。

我正在用 python 生成 tex 文件的内容,这将允许按打印字符的数量进行初始排序(消除格式化内容),但这并没有考虑到字体的属性。

一个例子(按第一个字符排序):

%19 chars of text
{\large\textbf Cellophane Tape Day}\par
%29 chars of text
{\miniscule Saturday Sixth Week Of Easter}\par
%50 chars of text
{\miniscule\bday{} {{\fontspec[Scale=MatchLowercase,Script=Greek]{Comic Sans MS}Σωκράτης Κόκκαλης}} ["{{\fontspec[Scale=MatchLowercase,Script=Latin]{Impact}Sokratis Kokkalis, 1939CE}}"]}\par
%46 chars of text (including RTL and LTR
{\miniscule{\RL{\fontspec[Scale=MatchLowercase,Script=Arabic]{Courier New}\char"200Fرمضان\char"200E}} [{{{\fontspec[Scale=MatchLowercase]{Calibri}}Ramaḍān Hilāl}} "{{\fontspec[Scale=MatchLowercase,Script=Latin]{Impact}1st day of Ramadan}}"]}\par
%39 chars of text
{\miniscule\bday{} {{\fontspec[Scale=MatchLowercase]{SimHei}唐德宗}} ["{{\fontspec[Scale=MatchLowercase,Script=Latin]{Impact}Emperor Dezong of Tang, 742CE}}"]}\par

在图片中,无序位于黄线上方,理想排序(例如)位于黄线下方。stackexchange 不允许我附加 2 张单独的图片。

在此处输入图片描述

通过手动重新排列行的顺序,我可以获得所需的顺序,但包含此功能的整体解决方案将根据计算的输入创建包含数百个集合的文件。因此,手动排序并不是特别可行。

生成第一个(未分类的)图像的 MWE:

\documentclass[10pt,twoside,openany,showtrimmarks]{memoir}
\RequirePackage{fontspec}
\RequirePackage{bidi}
\begin{document}
\font\bdayfont="Webdings" at 12pt
\DeclareRobustCommand{\bday}[1]{{\bdayfont \XeTeXglyph72}}
%19 chars of text
{\large\textbf Cellophane Tape Day}\par
%29 chars of text
{\miniscule Saturday Sixth Week Of Easter}\par
%50 chars of text
{\miniscule\bday{} {{\fontspec[Scale=MatchLowercase,Script=Greek]{Comic Sans MS}Σωκράτης Κόκκαλης}} ["{{\fontspec[Scale=MatchLowercase,Script=Latin]{Impact}Sokratis Kokkalis, 1939CE}}"]}\par
%46 chars of text (including RTL and LTR
{\miniscule{\RL{\fontspec[Scale=MatchLowercase,Script=Arabic]{Courier New}\char"200Fرمضان\char"200E}} [{{{\fontspec[Scale=MatchLowercase]{Calibri}}Ramaḍān Hilāl}} "{{\fontspec[Scale=MatchLowercase,Script=Latin]{Impact}1st day of Ramadan}}"]}\par
%39 chars of text
{\miniscule\bday{} {{\fontspec[Scale=MatchLowercase]{SimHei}唐德宗}} ["{{\fontspec[Scale=MatchLowercase,Script=Latin]{Impact}Emperor Dezong of Tang, 742CE}}"]}\par
\end{document}

答案1

这里有一个实现expl3(以及如何使用它的示例\foreach)。

这个想法是吸收要按长度排序的项目,然后测量它们并将宽度与索引一起存储在序列中;每个项目将是{<dimen>}{<number>}。然后我们可以根据第一部分对序列进行排序\dim_compare:nNnTF(它对第一个和第三个参数进行扩展以找到长度,因此\use_i:nn将提取第一部分)。一旦对该序列进行排序,我们就可以加载另一个序列,其中包含由第二部分索引的项目。

\documentclass{article}
\usepackage{xparse,pgffor}

\ExplSyntaxOn
\NewDocumentCommand{\sortbylength}{mm}
 {
  \eirikr_sortlen:nn { #1 } { #2 }
 }

\NewExpandableDocumentCommand{\getitem}{mm}
 {
  \seq_item:cn { g_eirikr_sortlen_#1_seq } { #2 }
 }

\NewExpandableDocumentCommand{\getnumber}{m}
 {
  \seq_count:c { g_eirikr_sortlen_#1_seq }
 }

\int_new:N \l__eirikr_sortlen_index_int
\box_new:N \l__eirikr_sortlen_temp_box
\seq_new:N \l__eirikr_sortlen_data_seq

\cs_new_protected:Nn \eirikr_sortlen:nn
 {
  % split the items into a sequence
  \seq_set_split:Nnn \l__eirikr_sortlen_input_seq { | } { #2 }
  % typeset each item and store its width and the index
  \int_zero:N \l__eirikr_sortlen_index_int
  \seq_clear:N \l__eirikr_sortlen_data_seq
  \seq_map_inline:Nn \l__eirikr_sortlen_input_seq
   {
    \int_incr:N \l__eirikr_sortlen_index_int
    \hbox_set:Nn \l__eirikr_sortlen_temp_box { ##1 }
    \seq_put_right:Nx \l__eirikr_sortlen_data_seq
     {
      { \dim_eval:n { \box_wd:N \l__eirikr_sortlen_temp_box } }
      { \int_eval:n { \l__eirikr_sortlen_index_int } }
     }
   }
  % sort the obtained items by the first part
  \seq_sort:Nn \l__eirikr_sortlen_data_seq
   {
    \dim_compare:nNnTF { \use_i:nn ##1 } > { \use_i:nn ##2 }
     { \sort_return_swapped: }
     { \sort_return_same: }
   }
  % prepare a sequence with the (non typeset) items
  \seq_gclear_new:c { g_eirikr_sortlen_#1_seq }
  \seq_map_inline:Nn \l__eirikr_sortlen_data_seq
   {
    \seq_gput_right:cx { g_eirikr_sortlen_#1_seq }
     {
      \seq_item:Nn \l__eirikr_sortlen_input_seq { \use_ii:nn ##1 }
     }
   }
 }
\ExplSyntaxOff

\begin{document}

\sortbylength{test}{
  abc |
  aabbcc |
  1234567890 |
  a
}

The list \texttt{test} has \getnumber{test} items. Here they are:

\foreach \x in {1,...,\getnumber{test}}
 {
  \getitem{test}{\x}\par
 }

\end{document}

在此处输入图片描述

通过第一个序列的示例

The sequence \l__eirikr_sortlen_input_seq contains the items (without outer braces):
>  {abc}
>  {aabbcc}
>  {1234567890}
>  {a}

然后是长度为

The sequence \l__eirikr_sortlen_data_seq contains the items (without outer braces):
>  {{15.27782pt}{1}}
>  {{30.27785pt}{2}}
>  {{50.00015pt}{3}}
>  {{5.00002pt}{4}}

排序后的序列为

The sequence \l__eirikr_sortlen_data_seq contains the items (without outer braces):
>  {{5.00002pt}{4}}
>  {{15.27782pt}{1}}
>  {{30.27785pt}{2}}
>  {{50.00015pt}{3}}

最后,完成这项工作后,根据索引构建最终序列:

The sequence \g_eirikr_sortlen_test_seq contains the items (without outer braces):
>  {a}
>  {abc}
>  {aabbcc}
>  {1234567890}

相关内容