Translate

2008年8月21日木曜日

シュウォーツ変換!

前回、シュウォーツ変換を勉強した際の記事を下記にて覚え書きしました。
れっつ、そーと。

で、その続きです。
前回のシュウォーツ変換では、ソートで使った値に重複がありませんでした。
もし、テストの得点順に並び替えるなんて時を考えた場合にある科目では
同じ点数の人がいたので、別の科目もつかって並び替えをしようとした場合を
考えてみます。

Excelで見たらどういうことかわかりよいですかねぇ??
ExcelでB列に名前、C列に国語の点数、D列に算数の点数が入っていたとします。
点数は、下の図の通りです。



それで、国語の点数で高い順に並び変えようと思ったのですが
tarou と jirou、saburou と shirouが同じ得点だったので
算数の得点も使って高得点な順に並び変えることにしました。
↓つまりこういうこと。



これを実行すると、下記のようになりますよね。



これをシュウォーツ変換を使ってやってみます。
use strict;
use warnings;

my %score = (
tarou => {
kokugo => 90,
sansuu => 10,
},
jirou => {
kokugo => 90,
sansuu => 50,
},
saburou => {
kokugo => 10,
sansuu => 10,
},
shirou => {
kokugo => 10,
sansuu => 90,
},
);

my @person = qw(tarou jirou saburou shirou);
my @ranking = map { $_->[0] }
sort { $b->[1] <=> $a->[1] || $b->[2] <=> $a->[2] }
map { [$_, $score{$_}{'kokugo'}, $score{$_}{'sansuu'} ]}
@person;

print "@ranking\n";


こんな感じになって実行すると…
jirou tarou shirou saburou
になります。

つまり、map-sort-mapのうち最後のmapでは、
map { ['並び替えたい物', '値1', '値2', ・・・, '値N'] }
としてあげればよくて
スペースシップ演算子では、左右で同じ値だと0を返すので
or演算子で同じ値だったら次の条件を使って判断してもらう
ようにすれば、いくらでも条件を追加していくことができます。
sort{ $b->[1] <=> $a->[1] || $b->[2] <=> $a->[2] || … $b->[N] <=> $a->[N] }
最初のmapはリファレンスの最初の要素を拾っているだけなので変わりません。
便利よいですね。

以上

0 件のコメント: