人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

Perlで条件に合うよう,ソートするプログラムを教えてください.
1行目を比較して,重複する配列で且つ添え字の若いもの(@array = <DATA>)を削除します.
以下結果です
Z 100 10 10
SC 200 5 9
SA 200 70 5
CC 100 100 9
BB 300 50 2
AA 100 70 5
c 5 0 0 9
上記の結果を元に,2行目の数字を比較して,降順にソートします.
BB 300 50 2
SC 200 5 9
SA 200 70 5
Z 100 10 10
CC 100 10 9
AA 100 70 5
c 5 0 0 9
上記の結果を元に,2行目が,同一の場合のペアのみを選び出して,3行目の数字を比較して,2行目の並びは崩さず降順にソートします.
BB 300 50 2
SA 200 70 5
SC 200 5 9
AA 100 70 5
CC 100 10 9
Z 100 10 10
c 5 0 0 9
上記の結果を元に,2,3行目が,同一のペアのみを選び出して,4行目の数字を比較して,降順にソートします.
BB 300 50 2
SA 200 70 5
SC 200 5 9
AA 100 70 5
Z 100 10 10
CC 100 10 9
c 5 0 0 9
以上のようなPerlプログラムを作りたいのですが,どなたか,動作するものを書いていただけないでしょうか?
宜しくお願い致します.
__DATA__
Z 100 10 10
AA 100 70 5
BB 200 50 1
SC 200 5 9
SA 200 70 5
AA 110 60 7
CC 160 10 9
BB 300 50 2
AA 100 70 1
c 5 0 0 9
以下,長々と続きます




●質問者: tifii
●カテゴリ:コンピュータ インターネット
✍キーワード:AA BB CC Perl SC
○ 状態 :終了
└ 回答数 : 2/2件

▽最新の回答へ

1 ● yoshifumi1975
●100ポイント ベストアンサー

data.txt

Z 100 10 10

AA 100 70 5

BB 200 50 1

SC 200 5 9

SA 200 70 5

AA 110 60 7

CC 100 10 9

BB 300 50 2

AA 100 70 5

c 5 0 0 9

my_sort.pl

use strict;

use Data::Dumper;

open my $fh, "data.txt";

my @data;

while(<$fh>){

chomp;

push @data, $_;

}

@data = remove_dup( @data );

@data = sort my_custom_sort @data;

foreach(@data){

print $_, "\n";

}

sub remove_dup{

my(@data)=@_;

my @new_data;

my %exists;

while(my $val = pop @data){

my @record = split /\s+/, $val;

unless( $exists{ $record[0] } ) {

unshift @new_data, $val;

$exists{ $record[0] }=1;

}

}

return @new_data;

}

sub my_custom_sort {

my(@a) = split /\s+/, $a;

my(@b) = split /\s+/, $b;

if($a[1]!=$b[1]){

return $b[1]<=>$a[1];

}

elsif($a[2]!=$b[2]){

return $b[2]<=>$a[2];

}

elsif($a[3]!=$b[3]){

return $b[3]<=>$a[3];

}

else{

return $b[4]<=>$a[4];

}

}

結果

BB 300 50 2

SA 200 70 5

SC 200 5 9

AA 100 70 5

Z 100 10 10

CC 100 10 9

c 5 0 0 9


「行」ではなくて「列」ですよね。あと、データと結果が食い違っているので混乱しました。

URLはダミーです。 http://d.hatena.ne.jp/yoshifumi1975/

◎質問者からの返答

回答いただきありがとうございます。

>「行」ではなくて「列」ですよね。あと、データと結果が食い違っているので混乱しました。

大変失礼いたしました。

動作の方は、Excelで作成したデータと完全に一致しました。

ありがとうございました!


2 ● kn1967
●30ポイント

PerlはWindows版バージョン5.8.8で動作確認

単純にprint出力しているだけですので、改行コードの追加等は適宜行ってください。

#読み込み
open("I","test.txt");
@a=<I>;
close("I");

#重複削除(一列目を比較して重複するものは添え字の若い者を削除)
@b=grep{!$count{(split(/ /,$_))[0]}++}sort{(split(/ /,$a))[0] cmp (split(/ /,$b))[0] || (split(/ /,$b))[1] <=> (split(/ /,$a))[1] || (split(/ /,$b))[2] <=> (split(/ /,$a))[2] || (split(/ /,$b))[3] <=> (split(/ /,$a))[3];}@a;

#並び替え(まず2列目数値降順、次に3列目数値降順、さらに4列目数値降順、最後に1列目文字列昇順)
@c=sort{(split(/ /,$b))[1] <=> (split(/ /,$a))[1] || (split(/ /,$b))[2] <=> (split(/ /,$a))[2] || (split(/ /,$b))[3] <=> (split(/ /,$a))[3] || (split(/ /,$a))[0] cmp (split(/ /,$b))[0];}@b;
print @c;

項目によるソートの動作確認には以下のように作業を順に複雑にしていってみてください。

#読み込み
open("I","test.txt");
@a=<I>;
close("I");

#項目による並び替え
@b=sort{(split(/ /,$a))[0] cmp (split(/ /,$b))[0];}@a;
print @b;

#複数項目による並び替え
# 1列目で比較して、同じであればさらに2列目で比較する
@c=sort{(split(/ /,$a))[0] cmp (split(/ /,$b))[0] || (split(/ /,$b))[1] <=> (split(/ /,$a))[1];}@a;
print @c;

#以下略
◎質問者からの返答

回答いただきありがとうございます。

WinXp,Perl5.8.8で環境は同じものですが、大量のデータを入れた時、

重複削除の部分が思った通りの動作をしませんでした。

恐らく、添え字の大きなものから削除されているのではないかと思います。

関連質問


●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ