電子書籍の厳選無料作品が豊富!

 自分のPerlの知識と能力では全くわからなかったので、ご質問いたします。今、タブ区切りのデータがあります。※下記のデータは便宜上、タブを/で表現しています。

現在、下記のようなデータが10万ぐらいあるのですが、10万の中から、タブの6、7、8番目の3つのデータで全く同じになった場合、カウントしたいと思っています。

<データ>
PB10_00045/10/B/神々/カミガミ/神々/カミガミ/名詞-普通名詞-一般/0/1/カミガミ/10/30/神々/0/1/1

PB10_00047/20/I/の/ノ/の/ノ/助詞-格助詞/0/1/ノ/30/40/の/0/1/1

PB10_00047/30/I/零落/レイラク/零落/レイラク/名詞-普通名詞-サ変可能/0/1/レーラク/40/60/零落/0/1/1



例えば、上の例であれば、6、7、8は次のようになりますが、
1つ目のデータ:6→神々、7→カミガミ、8→名詞-普通名詞-一般
2つ目のデータ:6→の、7→ノ、8→助詞-格助詞
3つ目のデータ:6→零落、7→レイラク、8→名詞-普通名詞-サ変可能
6、7、8の3つのデータでちがうので、下記のように文頭にそれぞれ頻度を1と表したいです。※3つでそろった場合のみ、カウントを増やしたいです。


1/PB10_00045/10/B/神々/カミガミ/神々/カミガミ/名詞-普通名詞-一般/0/1/カミガミ/10/30/神々/0/1/1

1/PB10_00047/20/I/の/ノ/の/ノ/助詞-格助詞/0/1/ノ/30/40/の/0/1/1

1/PB10_00047/30/I/零落/レイラク/零落/レイラク/名詞-普通名詞-サ変可能/0/1/レーラク/40/60/零落/0/1/1


現在、ウィンドウズの環境で、Perlは5.8を使っております。
どなたか、助けてくださると、幸いです。

A 回答 (5件)

#2になにも返事してないってことは丸投げ?


そもそも「ご質問」はないわな。

#!/usr/bin/perl
use strict;
use warnings;

my $delim = '/';
my %counts;
my %lines;

while (my $line = <DATA>) {
chomp $line;
my $key = join $delim, (split $delim, $line)[5,6,7];
$counts{$key}++;
$lines{$key} ||= $line;
}

foreach my $key (keys %lines) {
#printf "%d/%s\n", $counts{$key}, $lines{$key};
printf "%d/%s\n", $counts{$key}, $key;
}


__END__
PB10_00045/10/B/神々/カミガミ/神々/カミガミ/名詞-普通名詞-一般/0/1/カミガミ/10/30/神々/0/1/1
PB10_00047/20/I/の/ノ/の/ノ/助詞-格助詞/0/1/ノ/30/40/の/0/1/1
PB10_00047/30/I/零落/レイラク/零落/レイラク/名詞-普通名詞-サ変可能/0/1/レーラク/40/60/零落/0/1/1
PB10_00045/10/B/神々/カミガミ/神々/カミガミ/名詞-普通名詞-一般/0/1/カミガミ/10/30/神々/0/1/1
PB10_00047/20/I/の/ノ/の/ノ/助詞-格助詞/0/1/ノ/30/40/の/0/1/1
PB10_00047/30/I/零落/レイラク/零落/レイラク/名詞-普通名詞-サ変可能/0/1/レーラク/40/60/零落/0/1/1
PB10_00045/10/B/神々/カミガミ/神々/カミガミ/名詞-普通名詞-一般/0/1/カミガミ/10/30/神々/0/1/1
PB10_00047/20/I/の/ノ/の/ノ/助詞-格助詞/0/1/ノ/30/40/の/0/1/1
PB10_00048/20/I/の/ノ/の/ノ/名詞-非自立/0/1/ノ/30/40/の/0/1/1
PB10_00050/20/I/の/ノ/の/ノ/助詞-格助詞/0/1/ノ/30/40/の/0/1/1

>perl okw.pl
3/神々/カミガミ/名詞-普通名詞-一般
2/零落/レイラク/名詞-普通名詞-サ変可能
4/の/ノ/助詞-格助詞
1/の/ノ/名詞-非自立

十万件あったとして、みたとこデータ一件が100バイトそこそこですから
Perlが管理するために余計なものが引っ付いたとしても
PCのスペック次第でいけなくもないでしょう。
頻度表とやらで出力するときに行丸ごとが必要ないならその分減るでしょうし。
    • good
    • 0
この回答へのお礼

ありがとうございます。無事にできました!

お礼日時:2009/02/11 09:03

できなかったにしても, 単に「できなかった」とだけ書くのではなく「これこれこうなった」とまで書くようにしてほしい. 実際にどうなったかというのは, 考える上で大きなヒントになる. あなたの周りがどうかはさておいて, 一般に超能力者は多くないと推定されるんだから. 「回答しやすい質問」というものを心掛けてほしいなあ.


でなんだけど, これは「split をそのまま書いたんだろうな」と推測できる. もしそうなら, split するときにタブで区切るように直してくれ.
    • good
    • 0
この回答へのお礼

そうですね、そこが問題だったみたいです。便宜上、/を使ったのが、混乱を招いたみたいです。すみません・・・・

お礼日時:2009/02/11 09:04

面倒なことをしたくなかったらハッシュを使えばいいんじゃないの?


例えば
while (<>) {
++$occurence{join('/', (split(m!/!))[5, 6, 7])};
}
で終わり?
もちろん順序が重要なときにはそれなりの処理が必要ですが.

この回答への補足

この方法でやってみましたが、できませんでした・・

補足日時:2009/02/11 01:16
    • good
    • 0

10万件のデータというのが厄介だなぁ


そのデータはある程度固定であり、ごく希にしか内容が変化しない、と仮定の上にあれば、これで何とかなると思います。

1.6,7,8番目をソートキーとしてソートする。
2.前の行と現在の行を順番にチェックしていく
3.6,7,8,がそれぞれ同一内容ならカウントを増やし、違っていたらファイルへ追記出力
4.ループで無くなるまでやる
こんな感じでやれば、チェック出来るかな?

sort { (split(/\t/,$a))[$x]<=>(split(/\t/,$b))[$x]; } @array; //二次元配列を昇順ソートする $xにはソートキーになる配列番号を入れる
を使用して、6,7,8をそれぞれ1回ずつソートしたデータを作って、
後はループでガンガン。

問題点としては、一度ソートしてしまうので、順番が狂うと困る場合には、全行程終了後にソートし直す必要がある。ソート回数が多いので時間がかかる。
データを追記したり変更する場合には、それなりに凝ったアルゴリズムで対策した方がいい。
と、いろいろと面倒な部分もありますが、
これで何とかなりそうですか?
    • good
    • 0
この回答へのお礼

アドバイス、ありがとうございます。しかし、自分の知識では、このアドバイスに対応できなさそうです・・・

お礼日時:2009/02/11 09:06

6と7と8が=になったらカウントアップ、という事なのですか?


もしそうでしたら、splitとstrcmpあたりを使えば出来ますけど、
それでいいのでしょうか?
if文を少し組み合わせれば、出現頻度が調べれますけど

この回答への補足

わかりにくかったようで、申し訳ありません。それと、自分のやりたいことにちょっと問題もあったので、補足いたします。すみません。たとえば、下記のようであれば、6番目、7番目、8番目で全く同じ場合にカウントします。たとえば、下記のデータでは、2番目のデータは、6→の、7→ノ、8→助詞→格助詞ですが、3番目は6→の、7→ノ、8→名詞→非自立となり、3つすべてが同じではないので、別のものとしてカウントをしたいと思います。

<データ>
PB10_00045/10/B/神々/カミガミ/神々/カミガミ/名詞-普通名詞-一般/0/1/カミガミ/10/30/神々/0/1/1

PB10_00047/20/I/の/ノ/の/ノ/助詞-格助詞/0/1/ノ/30/40/の/0/1/1

PB10_00048/20/I/の/ノ/の/ノ/名詞-非自立/0/1/ノ/30/40/の/0/1/1

PB10_00050/20/I/の/ノ/の/ノ/助詞-格助詞/0/1/ノ/30/40/の/0/1/1




ここからちょっと訂正したいのですが、
頻度表では、6と7と8だけを取り出し、文頭に頻度をつけたいと思っております。


頻度表
<データ>
1/神々/カミガミ/名詞-普通名詞-一般

2/の/ノ/助詞-格助詞

1/の/ノ/名詞-非自立/

補足日時:2009/02/10 22:53
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!