単語の長い配列があり、それを長さの昇順で表示する必要があります。パッケージ arraysort を使用して比較器をカスタマイズしようとしました。
簡略化したコードは次のとおりです。
\documentclass{article}
\usepackage{calc}
\usepackage{arraysort}
\newlength{\somelength}
\newcommand{\showLen}[1]{#1 \setlength{\somelength}{\widthof{#1}}\the\somelength\\}
\def\IsPositive#1{%
TT\fi
\ifcat_\ifnum0<0#1 _\else A\fi
}
%customised comparator based on example from arraysort manual
\newcommand{\cmpLen}[2]{%
\edef\cmpA{\showLen{#1}}%
\edef\cmpB{\showLen{#2}}%
\if\IsPositive{\cmpA}%
\if\IsPositive{\cmpB}%
\arraysortcomparenum{\cmpA}{\cmpB}%
\else%
\togglefalse {arraysortresequal}%
\toggletrue{arraysortresult}%
\fi %
\else%
\if\IsPositive{\cmpB}%
\togglefalse{arraysortresequal}%
\togglefalse{arraysortresult}%
\else%
\arraysortcomparestr{\cmpA}{\cmpB}%
\fi %
\fi %
}
\begin{document}
\newarray{A}
\readarray{A}{Compulsion&His&Obsession&Girl&Relationship&His}%
\sortArray[cmpLen]{63}{A}
\A{1}\A{2}\A{3}\A{4}\A{5}
\end{document}
arraysort マニュアルの 4 ページにある「カスタム比較器を使用した \sortArray」の例を変更しました。変更点は の定義\cmpA
と、\cmpB
コマンド \showLen を使用して計算された長さを提供する部分です。
動作せず、表示されるエラーが明確ではありません。
! Undefined control sequence.
\GenericError ...
#4 \errhelp \@err@ ...
l.37 \A
{1}\A{2}\A{3}\A{4}\A{5}
なぜ私のコードが機能しないのですか? LaTeX のみを使用して配列を事前にソートせずにこれを行うより良い方法はありますか?
答え1
オプションも必要でしたcomparenum
。これで解決するようです。
コンパイル時間は、数十万行のコードがロードされたかのように、著しく長すぎます... ああ、わかりました。これは\sortArray[cmpLen]{63}{A}
OP のためです。これを に変更する\sortArray[cmpLen]{6}{A}
と、正常にコンパイルされます。
\documentclass{article}
\usepackage{calc}
\usepackage[comparenum]{arraysort}
\newsavebox\mybox
%\newlength{\somelength}
%\newcommand{\showLen}[1]{#1 \setlength{\somelength}{\widthof{#1}}\the\somelength\\}
\def\IsPositive#1{%
TT\fi
\ifcat_\ifnum0<0#1 _\else A\fi
}
%customised comparator based on example from arraysort manual
\newcommand{\cmpLen}[2]{%
\sbox\mybox{#1}\edef\cmpA{\number\wd\mybox}%
\sbox\mybox{#2}\edef\cmpB{\number\wd\mybox}%
\if\IsPositive{\cmpA}%
\if\IsPositive{\cmpB}%
\arraysortcomparenum{\cmpA}{\cmpB}%
\else
\togglefalse {arraysortresequal}%
\toggletrue {arraysortresult}%
\fi
\else
\if\IsPositive{\cmpB}%
\togglefalse {arraysortresequal}%
\togglefalse {arraysortresult}%
\else
\arraysortcomparenum{\cmpA}{\cmpB}%
\fi
\fi
}
\begin{document}
\newarray{A}
\readarray{A}{Compulsion&His&Obsession&Girl&Relationship&His}%
\sortArray[cmpLen]{63}{A}
\A(1)
\A(2)
\A(3)
\A(4)
\A(5)
\A(6)
\end{document}
生産する
His
His
Girl
Obsession
Compulsion
Relationship
答え2
expl3
以下はとを使用した実装ですl3sort
。 * バリアントは逆順にソートします。オプションの引数 (デフォルトは「カンマ スペース」) は、出力内の項目間の区切り文字です。
\documentclass{article}
\usepackage{xparse,l3sort}
\ExplSyntaxOn
% \sortwordsbylength has a *-variant (for reverse ordering),
% an optional argument with default value “comma space”
% and a mandatory argument
\NewDocumentCommand{\sortwordsbylength}{ s +O{,~} m }
{
\IfBooleanTF{#1}
{% for decreasing ordering we pass <
\kees_sort_bylength:nnn { < } { #2 } { #3 }
}
{% for increasing order we pass >
\kees_sort_bylength:nnn { > } { #2 } { #3 }
}
}
% some variables
\seq_new:N \l__kees_sort_items_seq
\box_new:N \l__kees_sort_boxa_box
\box_new:N \l__kees_sort_boxb_box
% the main macro
\cs_new_protected:Nn \kees_sort_bylength:nnn
{% split the input at commas
\seq_set_split:Nnn \l__kees_sort_items_seq { , } { #3 }
% sort the sequence according to l3sort
\seq_sort:Nn \l__kees_sort_items_seq
{
\hbox_set:Nn \l__kees_sort_boxa_box { ##1 }
\hbox_set:Nn \l__kees_sort_boxb_box { ##2 }
\dim_compare:nTF { \box_wd:N \l__kees_sort_boxa_box #1 \box_wd:N \l__kees_sort_boxb_box }
{ \sort_reversed: }
{ \sort_ordered: }
}
% print the sequence, with the stated separator between items
\seq_use:Nn \l__kees_sort_items_seq { #2 }
}
\ExplSyntaxOff
\begin{document}
\sortwordsbylength{Compulsion,His,Obsession,Girl,Relationship,His}
\bigskip
\sortwordsbylength*[\par]{Compulsion,His,Obsession,Girl,Relationship,His}
\end{document}