作者: 藤岡和夫
日時: 2005/10/08(12:04)
On Thu,  6 Oct 2005 13:31:37 +0900 (JST)
BYX06175@... (ほげほげ) さんwrote:

> 藤岡さんのスクリプトを見て、「必要な変数を用意して順番に
> 処理していったほうがわかりやすいな」と再認識しました。
> まとめてやろうとして、頭の中がパンクしていました。

 ほげほげさんの今回のテーマでは、sortによって初めて配列の要素の持つ属性、
すなわち配列の数値の持つ大きさの順番がわかり、しかも同じ大きさの数値を持
つ要素の数と仮に付与した順番からその順番を表す数値を得るための演算を行う
必要があり、最後に、元の配列ごとに要素に対応させて順番属性を付与する必要
があります。これらの作業を sortの一回のプロセスでやろうと思っても難しい
だろうと思います。まずsortしてから、並び替えた配列からforeachで必要な情
報を収集し、最後に元の配列を加工するというのが簡単でしょう。

 このような方法は一般的なプログラミングの手法というよりは問題の性質に依
存する知識を活用した解法と考えることができます。実際の手作業をプログラミ
ングに置き換えているだけなので、できたものを見ると簡単そうに見えますが、
やってみると意外と面倒です。どのようにforeachループの中で数値が動いてい
るのか、パズルのようになります。print文で意図どおりに数値が変化している
か調べながらプログラミングをするのがコツですね。

 シュワルツ変換は、ソート対象の配列要素と配列要素から計算して得られる新
しい要素をmapして、新しい要素をキーにソートして、元の配列要素を並び替え
るというものです。今回の場合はソートする必要はないので(というか、フィー
ルドの計算でソートを使っているので)、シュワルツ変換とは言えないですけど、
それ風に書けば(^^;)、mapを使って、

@a=(13, 18, 8, 9, 11, 20);
@b=(15, 9, 9, 18, 25);
foreach (sort {$a <=> $b} (@a, @b)){
    $nc{$_}++;$count++;
    if($_ == $buffer){
        $na{$_} +=  $count;
    }else{
        $na{$_} = $count; 
    }
    $buffer = $_;
}
foreach (keys %na){
    $ea{$_} = $na{$_}/$nc{$_};
}
@A = map { $_->[1] }
     map { [$_, $ea{$_}] } @a;# ブラケットで無名配列のリファレンスの生成
@B = map { $_->[1] }
     map { [$_, $ea{$_}] } @b;
print '@A = (', join(", ", @A), ")\n";
print '@B = (', join(", ", @B), ")\n";

 シュワルツ変換については、

[Tokyo.pm] Re: [Tokyo.pm] JUS感想
http://mail.pm.org/pipermail/tokyo-pm/1999-October/001928.html

が参考になります。Perlクックブックにはシュワルツ変換という用語では紹介さ
れていませんが、レシピ4.16の「計算可能なフィールドでリストをソートする」
にいろいろと出ていますから、参考になるでしょう。

藤岡 和夫
kazuf@...
TS Networkのために http://homepage1.nifty.com/kazuf/