現在、Perlを用いてBootstrap法という方法論によるデータの加工を行っています。
その中でハッシュを使います。
それはkeyでsortしvalueを並び替え、その並び替えたvalueを処理することが目的です。
例えばこのようなものです。
Height Weight
170.6 54.8
185.7 87.2
156.1 78.6
185.7 87.2
164.5 54.7
156.1 45.3
: :
以上のようなデータに対し、Heightをkeyにsortし、Weightを並び替え、その並び替えたWeightの値を上から順に同数ずつ、複数のグループに分類することが目的です。
ですがハッシュでは重複keyはvalueが上書きされてしまうので、元のデータより少なくなってしまい正確なsort、並び替えができません。
Perlでこの重複を回避する方法を教えていただきたく思います。
No.2ベストアンサー
- 回答日時:
どうしてもハッシュを使わなくていいなら、データを配列にしてsortするという手もありますが・・・
my @data=(
[170.6 , 54.8],
[185.7 , 87.2],
[185.7 , 87.2],
[185.7 , 87.2],
[185.7 , 87.2],
[156.1 , 78.6],
[185.7 , 87.2],
[164.5 , 54.7],
[156.1 , 45.3]);
@data = @data[sort {$data[$a][0] <=> $data[$b][0]} 0..$#data];
for my $i(0..$#data){
print "$data[$i][0] , $data[$i][1]<br>\n";
}
p.s.
@heightと@weightに分かれていて、@heightをkeyにして@weightをsortするなら、
@weight = @weight[sort {$height[$a] <=> $height[$b]} 0..$#height];
になります、たぶん。
なるほど、こんな方法があるのですね。
sort {$data[$a][0] <=> $data[$b][0]}
このような表記でsortできるのは違和感があるのですが、まだ私が『{$a<=>$b}』の意味を十分に理解していないのと、『0..$#height』という記述の仕方で、$dataを@data($data[$i])として扱えるということかと解しました。
早速試してみます。
ありがとうございました。
No.6
- 回答日時:
ANo.5さんへ。
ANo.3です。
>あと回答欄で間違いがあったら指摘してくれということなので。
>
>> $a <=> $bは、「$aと$bを数値として比べてね(昇順で)」という意味です。
>カッコ内が余計です。この比較自体にはソートを昇順でするか降順でするか
>の意味はありません。あくまで $a と $b を比較して
>$a > $ b のとき -1
>$a == $b のとき 0
>$a < $b のとき 1
>を返しているだけです。
すみません、そういう事(上)です。
余計な事書いて間違えてました。
返事が遅れてしまい申し訳ありません。
ANo.6さんはAno.3さんと同じ方のようなので、失礼とは思いますが併せてお礼申し上げます。
>@data = @data[sort {$data[$a][0] <=> $data[$b][0]} 0..$#data];
>の、0..$#dataは、配列の添え字です。
>わかりやすく言えば、(0,1,2,3,4,5,6,7,8)を作っただけです。
非常に分かり易い説明、ありがとうございます。
なるほど、そういうことだったのですね。
納得です。
>$a > $ b のとき -1
>$a == $b のとき 0
>$a < $b のとき 1
確かにこのことは参考書などにも記載されておりますが、私は何となくしかその意味を理解できていないんですよね。
要勉強です。
No.5
- 回答日時:
たぶんハッシュの要素に配列のリファレンスを入れるところで
詰まっていると思うので参考にでも。
use strict;
use warnings;
my %data;
while (my $entry = <DATA>) {
chomp $entry;
my ($height, $weight) = split q{,}, $entry;
if (!defined $data{$height}) {
$data{$height} = [];
}
push @{$data{$height}}, $weight;
}
foreach my $key (sort {$a <=> $b} keys %data) {
print $key, " : ", join(q{,}, @{$data{$key}}), "\n";
}
__DATA__
170.6,54.8
165.7,87.2
156.1,78.6
185.7,87.2
164.5,54.7
156.1,45.3
実行結果:
156.1 : 78.6,45.3
164.5 : 54.7
165.7 : 87.2
170.6 : 54.8
185.7 : 87.2
あと回答欄で間違いがあったら指摘してくれということなので。
> $a <=> $bは、「$aと$bを数値として比べてね(昇順で)」という意味です。
カッコ内が余計です。この比較自体にはソートを昇順でするか降順でするか
の意味はありません。あくまで $a と $b を比較して
$a > $ b のとき -1
$a == $b のとき 0
$a < $b のとき 1
を返しているだけです。
a とか b という名前は placeholder みたいなもの
なのであまり気にすることはないです。
返事が遅れてしまい申し訳ありません。
なるほど、理解できました。
分かり易い説明、ありがとうございます。
>if (!defined $data{$height}) {
>$data{$height} = [];
>}
>push @{$data{$height}}, $weight;
ここがキーポイントですね。
No.4
- 回答日時:
key に通し番号を付けてはどうでしょうか?
use strict;
my $no = 0; my %hash;
while (<DATA>) {
$no++;
my ($key, $value) = split /\s+/;
$hash{"${key}_$no"} = $value;
}
foreach my $key (sort { substr($a, 0, 5) <=> substr($b, 0, 5) or $hash{$a} <=> $hash{$b} } keys %hash) {
print substr($key, 0, 5), " $hash{$key}\n";
}
__DATA__
170.6 54.8
165.7 87.2
156.1 78.6
185.7 87.2
164.5 54.7
156.1 45.3
お返事が遅れ大変申し訳ありません。
通し番号を追加させるというのは思いつきませんでした。
ありがとうございます。
皆さんのご意見を参考に、無事に解決することができました。
本当にありがとうございました。
No.3
- 回答日時:
私は素人(完全独学)なので、本当に正しいかわからないのですが・・・
(間違ってたら、誰か指摘してください)
$a <=> $b
は、「$aと$bを数値として比べてね(昇順で)」という意味です。
では、$aと$b は何かと言うと、sortの作業中のある2つのデータです。
なぜa,bと言う名前なのかについては、特に意味は無いと思いますが・・・
で、
@data = @data[sort {$data[$a][0] <=> $data[$b][0]} 0..$#data];
の、0..$#dataは、配列の添え字です。
わかりやすく言えば、(0,1,2,3,4,5,6,7,8)を作っただけです。
そして、0,1,2,3,4,5,6,7,8を並べ替えて、新たな添え字を作っているのです。
例えば4と5を比べる時は、$data[4][0]と$data[5][0]を数値として比べてねと言う意味で、{$data[$a][0] <=> $data[$b][0]}と指示しています。
ちなみに、2番目のデータ(weight)をキーとして並び替えるなら、{$data[$a][1] <=> $data[$b][1]}です。
ここの指定しだいで、複数キーなど、複雑なsortをすることもできます。
たとえば、1番目のデータ(height)で並べ替えるんだけど、1番目のデータが同じ場合は2番目のデータ(weight)の降順でと言うなら、{$data[$a][0] <=> $data[$b][0] or $data[$b][1] <=> $data[$a][2]}になります、多分。
言葉で言いにくいので、以下を見てください。
実データを並び替えずに、並び替えられた添え字の配列を作る事ができます。
my @data=(
[170.6 , 54.8],
[185.7 , 87.2],
[185.7 , 87.2],
[185.7 , 87.2],
[185.7 , 87.2],
[156.1 , 78.6],
[185.7 , 87.2],
[164.5 , 54.7],
[156.1 , 45.3]);
print "content-type: text/html\n\n";
#最初のデータの状態
for my $i(0..$#data){print "$i : $data[$i][0] , $data[$i][1]<br>\n";}print "<br>\n";
#データ分の添え字の配列を作る
my @n=(0..$#data);
#上はmy @n=(0,1,2,3,4,5,6,7,8);と同じ意味
#最初の添え字の状態
for my $i(0..$#n){print "\$n[$i]=$n[$i]<br>\n";}print "<br>\n";
#0から8までの数値の配列を並び替える
#ただし、並び替えるルールが@dataの内容に依存する
@n=sort{$data[$a][0]<=>$data[$b][0]} @n;
#上は@n=sort{$data[$a][0]<=>$data[$b][0]} 0..$#n;と同じ
#並び替えられた添え字の状態
for my $i(0..$#n){print "\$n[$i]=$n[$i]<br>\n";}print "<br>\n";
#並び替えられた添え字順のデータ
for my $i(0..$#n){print "$data[$n[$i]][0] , $data[$n[$i]][1]<br>\n";}
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・街中で見かけて「グッときた人」の思い出
- ・「一気に最後まで読んだ」本、教えて下さい!
- ・幼稚園時代「何組」でしたか?
- ・激凹みから立ち直る方法
- ・1つだけ過去を変えられるとしたら?
- ・【あるあるbot連動企画】あるあるbotに投稿したけど採用されなかったあるある募集
- ・【あるあるbot連動企画】フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
- ・映画のエンドロール観る派?観ない派?
- ・海外旅行から帰ってきたら、まず何を食べる?
- ・誕生日にもらった意外なもの
- ・天使と悪魔選手権
- ・ちょっと先の未来クイズ第2問
- ・【大喜利】【投稿~9/7】 ロボットの住む世界で流行ってる罰ゲームとは?
- ・推しミネラルウォーターはありますか?
- ・都道府県穴埋めゲーム
- ・この人頭いいなと思ったエピソード
- ・準・究極の選択
- ・ゆるやかでぃべーと タイムマシンを破壊すべきか。
- ・歩いた自慢大会
- ・許せない心理テスト
- ・字面がカッコいい英単語
- ・これ何て呼びますか Part2
- ・人生で一番思い出に残ってる靴
- ・ゆるやかでぃべーと すべての高校生はアルバイトをするべきだ。
- ・初めて自分の家と他人の家が違う、と意識した時
- ・単二電池
- ・チョコミントアイス
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
int型(2バイト)データの分割
-
ポインター引数の関数でコンパ...
-
VisualBasicでレジストリキーの...
-
gnuplotの出力グラフ名を外部で...
-
'dataType' 引数を Null にする...
-
エクセルVBA:日付データの変換...
-
00月00日00時00分→0000年00月00...
-
ハッシュで重複キーを認める方...
-
10Mバイトて文字数に すると何...
-
Excel 1セル当りの文字数が2...
-
vbaからHTTP POST送信しても途...
-
char str[256]の256の意味は?
-
エクセルシート名の制限を変更...
-
日付時刻を4バイトに
-
CGIを勉強しています。¥n(改...
-
UTF-8で5~6バイトになる文字コ...
-
Excel VBA メール作成について ...
-
100MB
-
文字コードの使い分けについて
-
cookieにカンマ区切りでつめこ...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
ポインター引数の関数でコンパ...
-
stable diffusionのエラー
-
printfの%eで指数部分の桁数を...
-
エクセルVBA:日付データの変換...
-
int型(2バイト)データの分割
-
【Excel VBA】10進数を2進数に...
-
C#でのswitch文
-
C言語についてです! 同じ年の...
-
pythonでDBのカラム名で取得し...
-
PINVOKEで構造体配列をマーシャ...
-
MySQLに登録すると文字化け
-
C言語 ファイル内のデータと入...
-
CreateProcessでの環境変数の設...
-
'dataType' 引数を Null にする...
-
linuxのシェルでファイル名に先...
-
Cのプログラムがどうしても動き...
-
POSTで配列のデータを渡す方法は?
-
マクロ登録したピボットが重い...
-
gnuplotの出力グラフ名を外部で...
-
離散フーリエ変換のプログラム...
おすすめ情報