按字母顺序对姓名序列进行排序

按字母顺序对姓名序列进行排序

我的论文中有很多需要致谢的人,我想知道是否可以自动对他们的姓名进行排序,而不是手动排序。换句话说,我想要一个宏,比如说\sorted,它可以

\sorted{Gauss, Carl Friedrich and Riemann, Bernhard and Euler, Leonhard}

和输出

伦纳德·欧拉、卡尔·弗里德里希·高斯和伯恩哈德·黎曼

明确地说,我不是希望对列表环境中的项目进行排序。相反,我想输出一个包含各种名称的句子,按字母顺序排列。除最后两个之外的所有名称都应以 分隔,,而最后两个名称应以 分隔and

答案1

这是你想要的吗?我定义了一些排序规则:

  • AA: [a-zA-Z]
  • raA:[Z-Az-a]
  • Aa:[A-Za-z]
  • rAa: [z-aZ-A]

您还可以定义您的所有者排序规则。

在此处输入图片描述

\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn

\tl_new:N \l__seq_sep_tl
\seq_new:N \l__alph_seq
\seq_new:N \l__Alph_seq
\seq_new:N \l__Alphalpa_seq
\seq_new:N \l__alphAlph_seq
\seq_new:N \l__ralph_seq
\seq_new:N \l__rAlph_seq
\seq_new:N \l__rAlphalpa_seq
\seq_new:N \l__ralphAlph_seq
\seq_new:N \l__result_seq
\seq_new:N \l__custom_order_seq
\bool_new:N \l__if_less_bool
\prop_new:N \l__order_prop

\seq_set_from_clist:Nn \l__alph_seq
  { a,b,c,d,e,f,g,h,i,g,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z }
\seq_set_from_clist:Nn \l__Alph_seq
  { A,B,C,D,E,F,G,H,I,G,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z }
\seq_set_from_clist:Nn \l__Alphalph_seq
  {
    A,B,C,D,E,F,G,H,I,G,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,
    a,b,c,d,e,f,g,h,i,g,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z
  }
\seq_set_from_clist:Nn \l__alphAlph_seq
  {
    a,b,c,d,e,f,g,h,i,g,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,
    A,B,C,D,E,F,G,H,I,G,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z
  }
\seq_set_eq:NN \l__ralph_seq \l__alph_seq
\seq_set_eq:NN \l__rAlph_seq \l__Alph_seq
\seq_set_eq:NN \l__ralphAlph_seq \l__alphAlph_seq
\seq_set_eq:NN \l__rAlphalph_seq \l__Alphalph_seq
\seq_reverse:N \l__ralph_seq
\seq_reverse:N \l__rAlph_seq
\seq_reverse:N \l__ralphAlph_seq
\seq_reverse:N \l__rAlphalph_seq
\seq_set_eq:NN \l__custom_order_seq \l__Alphalph_seq

\prop_set_from_keyval:Nn \l__order_prop
  {
    a = alph,
    A = Alph,
    aA = alphAlph,
    Aa = Alphalph,
    ra = ralph,
    rA = rAlph,
    raA = ralphAlph,
    rAa = rAlphalph,
  }

\keys_define:nn { sort }
  {
    order .code:n = { \set_order_from_option:n { #1 } },
    sep .tl_set:N = \l__seq_sep_tl,
  }

\cs_new_protected:Nn \set_sort_order_from_seq:N
  {
    \int_zero:N \l_tmpa_int
    \seq_remove_duplicates:N #1
    \seq_map_inline:Nn #1
      {
        \int_incr:N \l_tmpa_int
        \int_if_exist:cF { g__sort_##1 }
          {
            \int_new:c { g__sort_##1 }
          }
        \int_gset_eq:cN { g__sort_##1 } \l_tmpa_int
      }
  }

\prg_new_protected_conditional:Nnn \str_if_less:nn { T, F, TF }
  {
    \int_set:Nn \l_tmpa_int
      { \str_count_ignore_spaces:n { #1 } }
    \int_set:Nn \l_tmpb_int
      { \str_count_ignore_spaces:n { #2 } }
    \int_compare:nTF { \l_tmpa_int < \l_tmpb_int }
      { \bool_set_true:N \l__if_less_bool }
      { \bool_set_false:N \l__if_less_bool }
    \int_step_inline:nn { \int_min:nn { \l_tmpa_int } { \l_tmpb_int } }
      {
        \int_set_eq:Nc \l_tmpa_int
          { g__sort_\str_item:nn { #1 } { ##1 } }
        \int_set_eq:Nc \l_tmpb_int
          { g__sort_\str_item:nn { #2 } { ##1 } }
        \int_compare:nF { \l_tmpa_int = \l_tmpb_int }
          {
            \int_compare:nTF { \l_tmpa_int < \l_tmpb_int }
              { \bool_set_true:N \l__if_less_bool }
              { \bool_set_false:N \l__if_less_bool }
            \prg_break:
          }
      }
    \bool_if:NTF \l__if_less_bool
      { \prg_return_true: }
      { \prg_return_false: }
  }

% #1 seq to be sorted #2 predefined order seq
\cs_new_protected:Nn \seq_sort_by_order:NN
  {
    \set_sort_order_from_seq:N #2
    \seq_sort:Nn #1
      {
        \str_if_less:nnTF { ##1 } { ##2 }
          { \sort_return_same: }
          { \sort_return_swapped: }
      }
  }


\cs_generate_variant:Nn \seq_set_split:Nnn { Nxo }
\cs_new_protected:Nn \sort_custom_seq:nn
  {
    \keys_set:nn { sort }
      {
        sep = {,},
        #1
      }
    \seq_set_split:Nxo \l__result_seq { \l__seq_sep_tl } { #2 }
    \seq_sort_by_order:NN \l__result_seq \l__custom_order_seq
  }

% #1 seq handle function #2 options #3 list
\cs_new_protected:Nn \sort_custom_seq:Nnn
  {
    \sort_custom_seq:nn { #2 } { #3 }
    #1 \l__result_seq
  }

\cs_new_protected:Nn \my_transpose:N
  {
    \seq_clear_new:N \l__new_seq
    \seq_map_inline:Nn #1
      {
        \seq_clear_new:N \l__item_seq
        \seq_set_split:Nnn \l__item_seq { , } { ##1 }
        \seq_reverse:N \l__item_seq
        \seq_put_right:Nx \l__new_seq { \seq_use:Nn \l__item_seq { ~ } }
      }
    \seq_set_eq:NN #1 \l__new_seq
  }

\cs_new_protected:Nn \set_order_from_seq:nn
  {
    \seq_set_split:Nnn \l__custom_order_seq { #1 } { #2 }
  }

\cs_new_protected:Nn \set_order_from_str:n
  {
    \str_set:Nn \l_tmpa_str { #1 }
    \seq_clear:N \l__custom_order_seq
    \str_map_inline:Nn \l_tmpa_str
      {
        \seq_put_right:Nn \l__custom_order_seq { ##1 }
      }
  }

\cs_new_protected:Nn \set_order_from_option:n
  {
    \prop_if_in:NnTF \l__order_prop { #1 }
      {
        \seq_set_eq:Nc \l__custom_order_seq
          { l__\prop_item:Nn \l__order_prop { #1 }_seq }
      }
      {
        \set_order_from_str:n { #1 }
      }
  }

\NewDocumentCommand { \setorder } { o m }
  {
    \IfNoValueTF { #1 }
      { \set_order_from_str:n { #2 } }
      { \set_order_from_seq:nn { #1 } { #2 } }
  }

\NewDocumentCommand { \mysorted } { O{} +m }
  {
    \sort_custom_seq:Nnn \my_transpose:N { #1 } { #2 }
    \seq_use:Nnnn \l__result_seq { ~and~ } { ,~ } { ~and~ }
  }

\NewDocumentCommand { \sorted } { m +m }
  {
    \sort_custom_seq:nn { order = #1 } { #2 }
    \makebox[4cm][l]{\bfseries Order:~#1}
    \seq_map_inline:Nn \l__result_seq
      {
        \makebox[1.2cm][l]{##1}
      }
  }

\ExplSyntaxOff

\begin{document}
\mysorted[sep=and]{Gauss, Carl Friedrich and Riemann, Bernhard and Euler, Leonhard}

\def\test{app, band, apple, Apple, App}
\sorted{aA}{\test}

\sorted{raA}{\test}

\sorted{Aa}{\test}

\sorted{rAa}{\test}

\sorted{ab-+*@c}{abc, c@-, b+@, @cb, b-c}
\end{document}

答案2

冒泡排序器,是我根据 David 对我的问题的回答修改而改编的尝试消除递归过程中的堆栈溢出

\sortlist宏是冒泡排序器(来自参考答案,但使用and而不是,作为列表分隔符)。但是,它将结果保留为 的形式Last Name, First and ...

我必须添加\rework宏来制作它First Last Name并用来\whichsep选择是否应该在名称之间插入,and,具体取决于它们在列表中的位置。

无需包裹!

\documentclass[10pt]{article}
\newcommand\alphabubblesort[1]{\def\sortedlist{}%
  \expandafter\sortlist#1 and \cr and \relax
  \expandafter\rework\sortedlist and \relax}
\def\sortlist#1and #2and #3\relax{%
  \let\next\relax
  \ifx\cr#2\relax%
    \edef\sortedlist{\sortedlist#1}%
  \else
    \picknext#1!and #2!\relax%
    \if F\flipflop%
      \edef\sortedlist{\sortedlist#1and }%
      \def\next{\sortlist#2and #3\relax}%
    \else%
      \let\tmp\sortedlist%
      \def\sortedlist{}%
      \def\next{\expandafter\sortlist\tmp#2and #1and #3\relax}%
    \fi%
  \fi%
\next
}
\def\picknext#1#2and #3#4\relax{%
  \ifnum\the\lccode`#1<\the\lccode`#3\relax
    \xdef\flipflop{F}%
  \else%
    \ifnum\the\lccode`#1>\the\lccode`#3\relax%
      \xdef\flipflop{T}%
    \else%
      \ZZfifi{\picknext#2!and #4!\relax}%
    \fi%
  \fi%
}
\def\ZZfifi#1\fi\fi{\fi\fi#1}
\def\rework#1, #2and #3\relax{#2#1\ifx\relax#3\relax\else
  \whichsep#3,\relax\rework#3\relax\fi}
\def\whichsep#1,#2,#3\relax{\ifx\relax#3\relax\ and \else, \fi}
\begin{document}
\def\mydata{%
Gauss, Carl Friedrich and Riemann, Bernhard and Euler, Leonhard}
\alphabubblesort{\mydata}

I wish to thank 
\alphabubblesort{%
Gauss, Carl Friedrich and 
Riemann, Bernhard and 
Euler, Leonhard and 
Bach, Carl Philipp Emanuel and 
Dumbledore, Albus Percival Wulfric Brian and 
Granger, Hermione Jean and 
Scott Thomas, Kristin and 
Van Gogh, Vincent and 
Sartre, Jean-Paul and 
Toulouse-Lautrec, Henri de}
for their valuable comments and incisive critiques.
\end{document}

在此处输入图片描述

答案3

这是一个基于 LuaLaTeX 的解决方案。它设置了一个名为 的 LaTeX 宏\sorted,该宏调用一个名为 的 Lua 函数sorted来完成大部分工作。单词and被视为分隔人员的关键字,而,(逗号) 是全名中姓氏和名字部分之间的分隔符。全名中的名字和名字部分都允许使用空格字符和连字符。

在此处输入图片描述

% !TeX program = lualatex
\documentclass{article}

%% Lua-side code
\usepackage{luacode} % for 'luacode' environment
\begin{luacode}
function string_to_table ( str )
   local namelist = {} -- initialize the table
   str:gsub ( "([^;]*)" , function ( name ) 
        -- Strip off any leading and trailing whitespace:
        name = name:gsub ( "^%s*(.-)%s*$" , "%1" )
        -- Insert 'name' in 'namelist'
        table.insert ( namelist , name )   
        end )
   return namelist
end

function sorted ( s )
   local t
   -- Change the separator keyword "and" to ";"
   s = s:gsub ( "and" , ";" )
   -- Convert to a Lua table:
   t = string_to_table ( s )
   -- Sort the table entries alphabetically:
   table.sort ( t )
   n = #t -- Retrieve number of entries
   -- Change "Surname, FirstName" to "FirstName Surname":
   for i=1,n do
     t[i] = string.gsub ( t[i] , "([%a%s%-]+)%,%s?(.+)" , "%2 %1" )
   end
   -- Output a string, using "and" as the final separator
   s = t[1]
   for i = 2,n-1 do s = s .. ", " .. t[i] end
   s = s .. " and " .. t[n]
   tex.sprint ( s )
end

\end{luacode}
%% LaTeX-side code:
\newcommand\sorted[1]{\directlua{sorted(\luastringN{#1})}}

\begin{document}
I wish to thank 
\sorted{Gauss, Carl Friedrich and Riemann,Bernhard and Euler, Leonhard and 
Bach, Carl Philipp Emanuel and Dumbledore,Albus Percival Wulfric Brian and 
Granger, Hermione Jean and Scott Thomas, Kristin and Van Gogh, Vincent and 
Sartre, Jean-Paul and Toulouse-Lautrec, Henri de}
for their valuable comments and incisive critiques.
\end{document}

答案4

这不是一个完整的答案,但问题也不完整。正如我上面的评论一样,我根据这个问题给出了答案:按字母顺序显示 itemize 中的项目

我修改了序言中的三行:本质上,没有必要输出一份清单,只是因为你输入作为列表。我认为这是你对我的评论最大的不满。

\documentclass{article}
\usepackage{datatool}% http://ctan.org/pkg/datatool
\newcommand{\sortitem}[1]{%
  \DTLnewrow{list}% Create a new entry
  \DTLnewdbentry{list}{description}{#1}% Add entry as description
}
\newenvironment{sortedlist}{%
  \DTLifdbexists{list}{\DTLcleardb{list}}{\DTLnewdb{list}}% Create new/discard old list
}{%
  \DTLsort{description}{list}% Sort list
  %\begin{itemize}% THIS LINE CHANGED
    \DTLforeach*{list}{\theDesc=description}{%
      \theDesc{} and }% THIS LINE CHANGED
  %\end{itemize}% THIS LINE CHANGED
}
\begin{document}

\begin{sortedlist}
    \sortitem{Gauss, Carl Friedrich}
    \sortitem{Riemann, Bernhard}
    \sortitem{Euler, Leonhard}
\end{sortedlist}

\end{document}

这输出

欧拉、莱昂哈德和高斯、卡尔·弗里德里希和黎曼、伯恩哈德和

您的剩余隐含问题部分(用逗号和“and”分隔的输出列表)可能已回答迭代逗号分隔的参数或者对电子工具箱列表中第一个和/或最后一个项目的特殊处理

相关内容