perlでちょっと複雑なソート3
この問題、さらに改良してみる。
studies.hatenablog.com
#! /usr/bin/perl -a use 5.010; use sort 'stable'; push @lines, $_; $priority{$F[1]} //= $.; END { print (sort { $priority{(split /\s+/, $a)[1]} <=> $priority{(split /\s+/, $b)[1]} } @lines); }
awk風のループを仮定する-aオプションをつけて、フィールド変数@Fを使えるようにする。
@Fはawkでいうところの$1,$2,...と同じ(ただし添え字は0始まり)。
これを用いて優先度をハッシュで作成する。
$countの代わりに使っている$.はawkでいうところのNRで、行番号。
メインループで優先度の設定をした後、ENDブロックでソートして出力。
%prefというハッシュは今回は使わず、ソートの際に行そのものからsplitとリストスライスで要素を取り出している。
(ここでも@Fが使えればいいけれど…)。
これはほぼ、excelでやったのと同じアルゴリズムだ。
excelではC2に以下を書いて、これをオートフィル&C列をキーにして並び替えしたのだった。
=iferror(match($b2, $b$1:$b1, 0), row())
もちろんexcelでやったのと比べれば、計算量はだいぶ減っている。
ちなみに、私の環境ではデフォルトで安定ソートの模様なので、実は"use sort 'stable';"のくだりもいらないのではという気もしたが、ちゃんとperldocに以下の記述がある。
The default algorithm is mergesort, which will be stable even if you do not explicitly demand it. But the stability of the default sort is a side-effect that could change in later versions. If stability is important, be sure to say so with a
use sort 'stable';
デフォルトのアルゴリズムはマージソートなので、あなたが安定を望んでいることを明示しなくても、安定にソートされる(動くことは動く)。しかし、このデフォルトは後のバージョンで変更になるかもしれない。もし安定性が大切なら、use sort 'stable';と書くこと。
今回は安定性が大切なので、書かなければならない。