読者です 読者をやめる 読者になる 読者になる

studies

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

perlでちょっと複雑なソート

perl

まただいぶ間が空いてしまった。

その間に私は、基本情報技術者という資格試験を受けたり、引っ越したりしていた。

最近少し落ち着いてきたし、間が空きすぎるのもよくないので、余りネタはないものの何か書いてみようと思う。



数か月前、excelでちょっと複雑なソートをやってみた。
studies.hatenablog.com


今回は、これをperlでやってみよう。

#! /usr/bin/perl
use 5.010;

while (<>) {
    ($city, $pref) = split;
    $pref{$city} = $pref;
    $pref_priority{$pref} //= ++$count;
    $city_priority{$city} = ++$times{$pref};
}
for (sort {$pref_priority{$pref{$a}} <=> $pref_priority{$pref{$b}} or
        $city_priority{$a} <=> $city_priority{$b}} keys(%pref)) {
    printf "%-15s%s\n", $_, $pref{$_};
}

市区町村から都道府県へのハッシュ、都道府県の優先度を表すハッシュ、同じ都道府県のとき市区町村の優先度を表すハッシュ、同じ都道府県が現れた回数を記録するハッシュの4つを用意する。
defined-or演算子を用いて、都道府県の優先度が設定されていない時(つまり一度だけ)優先度を設定する。
市区町村の優先度は、都道府県が現れた回数として設定する。

最後に、宇宙船演算子を用いてソートのルールを指定する。
複数のルールがあるときは、orでつなげばOK。

実行画面はこうなる。

$ cat city.txt 
京都市      京都府
千代田区    東京都
高岡市      富山県
松本市      長野県
宮津市      京都府
川崎市      神奈川県
諏訪市      長野県
渋谷区      東京都
滑川市      富山県
新宿区      東京都
臼杵市      大分県
稚内市      北海道
氷見市      富山県
いわき市    福島県
長野市      長野県
横須賀市    神奈川県
宇治市      京都府

$ ./sort.pl city.txt 
京都市      京都府
宮津市      京都府
宇治市      京都府
千代田区   東京都
渋谷区      東京都
新宿区      東京都
高岡市      富山県
滑川市      富山県
氷見市      富山県
松本市      長野県
諏訪市      長野県
長野市      長野県
川崎市      神奈川県
横須賀市   神奈川県
臼杵市      大分県
稚内市      北海道
いわき市   福島県

ありゃ、なんかズレた。

今回はちょっとおしゃれ(?)にハッシュを多用して書いてみた。
しかし、ちょっと調べたところによれば、

use 'stable';

などと書けば、perlでも安定ソートを使うこともできるようだ。
普通に1行ずつ配列に格納して、一気にバーンとソートしたほうがもっと短く(易しく)書けるだろう。