studies

いろいろ勉強用備忘録的な感じ

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())

studies.hatenablog.com

もちろん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';と書くこと。

今回は安定性が大切なので、書かなければならない。