sortについて

[上に] [前に] [次に]
まきろん 2000/05/20(土) 03:47:05
sortについてはいろいろ過去ログを検索したのですがいまいちわかりません。
ぐたい的には
データ1<>125<>おはよう<>
データ2<>134<>こんにちは<>
データ3<>14<>こんばんわ<>
データ4<>121<>おやすみ<>

こんなデータがあるとします。

これの最後の挨拶をあいうえお順でsortしたいのです。
挨拶はすべてひらがなです。

表示部は
おはよう、データ1(125)
おやすみ、データ4(121)
こんにちは、データ2(134)
こんばんわ、データ3(14)

こんなふううに表示させたいです。50音です。
どうか、どんなふううにやったらよいか
ご指導賜りますよう。

ふじ 2000/05/20(土) 04:38:26
Perl で、文字コードが EUC という前提で答だけ書くなら、
--
$dat[0] = 'データ1<>125<>おはよう<>';
$dat[1] = 'データ2<>134<>こんにちは<>';
$dat[2] = 'データ3<>14<>こんばんわ<>';
$dat[3] = 'データ4<>121<>おやすみ<>';

@sorted = sort { (split(/<>/, $a))[2] cmp (split(/<>/, $b))[2] } @dat;

for (@sorted){
    split(/<>/);
    print "$_[2], $_[0]($_[1])\n";
}
--
こんなのですが。(速度、効率は無視してます)

ポイントは、
sort { 比較式 }
で、sort 関数の並び(ソート)順が決定される(比較される二つの値は
$a, $b として参照)、ということでしょうか。

sadahiro 2000/05/20(土) 07:19:00
五十音順をきちんと(辞書のように)行おうとしたら
文字コード順ではうまくないのではないでしょうか.
とりあえず広辞苑順を参考に書いてみましたがどうでしょうか.
(Perl5です)なんかややししいので間違えているかも...

sub kanasort{
my %kana = (
"ぁ" => "01b", "ぃ" => "02b", "ぅ" => "03b", "ぇ" => "04b", "ぉ" => "05b",
"あ" => "01a", "い" => "02a", "う" => "03a", "え" => "04a", "お" => "05a",
"か" => "11a", "き" => "12a", "く" => "13a", "け" => "14a", "こ" => "15a",
"が" => "11b", "ぎ" => "12b", "ぐ" => "13b", "げ" => "14b", "ご" => "15b",
"さ" => "21a", "し" => "22a", "す" => "23a", "せ" => "24a", "そ" => "25a",
"ざ" => "21b", "じ" => "22b", "ず" => "23b", "ぜ" => "24b", "ぞ" => "25b",
"た" => "31a", "ち" => "32a", "つ" => "33a", "て" => "34a", "と" => "35a",
                              "っ" => "33b",
"だ" => "31b", "ぢ" => "32b", "づ" => "33c", "で" => "34b", "ど" => "35b",
"な" => "41a", "に" => "42a", "ぬ" => "43a", "ね" => "44a", "の" => "45a",
"は" => "51a", "ひ" => "52a", "ふ" => "53a", "へ" => "54a", "ほ" => "55a",
"ば" => "51b", "び" => "52b", "ぶ" => "53b", "べ" => "54b", "ぼ" => "55b",
"ぱ" => "51c", "ぴ" => "52c", "ぷ" => "53c", "ぺ" => "54c", "ぽ" => "55c",
"ま" => "61a", "み" => "62a", "む" => "63a", "め" => "64a", "も" => "65a",
"ゃ" => "71a",                "ゅ" => "73b",                "ょ" => "75b",
"や" => "71a",                "ゆ" => "73a",                "よ" => "75a",
"ら" => "81a", "り" => "82a", "る" => "83a", "れ" => "84a", "ろ" => "85a",
"わ" => "91a", "ゐ" => "92a", "ゑ" => "93a", "を" => "94a", "ん" => "95a",
);

my @ak = map {$kana{$_}} split(/(..)/,$_[0]);
my @bk = map {$kana{$_}} split(/(..)/,$_[1]);
my $i;
for ($i=0; $i<=(@ak>@bk?@ak:@bk); $i++) {
if($ak[$i] != $bk[$i]) {return $ak[$i] <=> $bk[$i]}
}
for ($i=0; $i<=(@ak>@bk?@ak:@bk); $i++) {
if($ak[$i] ne $bk[$i]) {return $ak[$i] cmp $bk[$i]}
}
return 0;
}

@data = qw(かめ はんだ ぱんだ ぱん はんこ ばなな ばんごう がっこう かった かつた);
print join "\n", sort{&kanasort($a,$b)} @data;

<出力>
がっこう
かつた
かった
かめ
ばなな
ぱん
はんこ
ばんごう
はんだ
ぱんだ

sadahiro 2000/05/20(土) 07:34:06
それで,ふじさんの回答に&kanasortを組み込むなら,
次のようにしましょう
(sub kanasort{} の位置は前でも後でもいいでしょう.
サブルーチンですから宣言はお好きなところに)

$dat[0] = 'データ1<>125<>はね<>';
$dat[1] = 'データ2<>134<>ばね<>';
$dat[2] = 'データ3<>14<>はは<>';

@sorted = sort {&kanasort((split(/<>/, $a))[2],(split(/<>/, $b))[2]) } @dat;
for (@sorted){
    split(/<>/);
    print "$_[2], $_[0]($_[1])\n";
}

sub kanasort{
― 略 ―
}

sadahiro [E-Mail] 2000/05/20(土) 07:43:02
やはり間違えていました.

"ゃ" => "71b",

でなくては.

[上に] [前に] [次に]