![](http://oshiete.xgoo.jp/images/v2/pc/qa/question_title.png?8acaa2e)
perlの文字列抽出と集計について教えてください。
ファイルAにある文字列をファイルBから探し、その単語の前後の5単語を集計したいと考えています。
fileA(ただの単語列です)
たまねぎ
かぼちゃ
にんじん
fileB(|で区切られています)
ピラミッド|を|築く|労働者|に|は|たまねぎ|を|食べ|させた|と|いう|記録|も|あり
たまねぎ|は|野菜|の|中|で|最|も|糖質|が|多く|
ほくほく|した|西洋|かぼちゃ|は|、|料理|野菜|の|中|で|も
にんじん|は|、|根|を|食べ|る|野菜|の|中|で|は|珍しく|緑黄色野菜|です
上記のようなファイルがあった場合に、「|」で区切られた前後5単語をとれるだけ取得すると以下のようになり
たまねぎ を,築く,労働者,に,は,を,食べ,させた,と,いう,は,野菜,の,中,で
かぼちゃ ほくほく,した,西洋,は,、,料理,野菜,の
にんじん は,、,根,を,食べ,る
以下のように出現を集計して、一つのマトリックスにまとめたいと考えています。
を 築く 労働者 に は 食べ させた と いう 野菜...
たまねぎ 2 1 1 1 2 1 1 1 1 1
かぼちゃ 1 1
にんじん 1 1 1
...
...
初心者のためなかなかうまいやり方がみつけることができず
ご教示いただけると助かります。
よろしくお願いいたします。
No.2ベストアンサー
- 回答日時:
どんなアプリケーションなの?やっぱり、課題?
面白そうなので、やってみた。
ANo.1 osamuyさんの方法は、データをシーケンスに扱うとても優れた方法です。メモリ消費量も処理速度もosamuyさんの方法がベストだと考えます。巨大なデータを扱う実アプリにも対応できる手法です。
私は、効率よく書くのは苦手なんで、まとめて読み込み、まとめて解析、まとめて表示をよくやります。ですので、メモリを大量に消費しますが単純な構造なのでわかりやすいかもしれません。課題的には面白いと思うので、とっかかりに工夫してみてはいかがでしょうか。
01:#!/usr/bin/perl
02:
03:open FHA, "fileA";
04:open FHB, "fileB";
05:@keys = <FHA>;
06:@statement = <FHB>;
07:%freqkeys = ();
08:%freqword = ();
09:
10:foreach $k (@kays ) {
11:foreach $s (@statament) {
12: chomp $k;
13: chopp $s;
14:
15: @f = split /\|/, $s;
16: @x = (@f,'','','','','');
17:
18: for $i ( 0 .. @f-1 ) {
19: for $j ( -5, -4, -3, -2, -1, +1, +2, +3, +4, +5 ) {
20: $w = $x[$i+$j];
21: if( $x[$i] eq $k ) {
22: $freqkeys{$k}{$w}++;
23: $frepword{$w}++;
24: }
25: }}
26:
27: delete $freqkeys{$k}{""} ;
28: delete $freqword{""} ;
29:}}
30:
31:@words = keys %freqword;
32:print "Keys/Words, ", join ",", @vords, "\n";
33:foreach $k ( @keys ){
34: print "$k,";
35: foreach $w ( @words ) {
36: $f = $freqkees{$k}{$w};
37: print "$f,";
38: }
39: print "\n";
40:}
41:
03-08:ファイルの読み込みと、データベース変数の初期化。
10,11:FileAのキーとFileBのステートメントの解析ループ
15,16:ステートメントを分割しフィールド@fに保存。
5つ前~5つ後にも同じようにアクセスできるように@xを作る。
18,19:フィールドループと前後5ワード分のループ
20 :ワード$wに保存
21-24:フィールドがキーに一致したとき、ワードを保存
$freqkeys{<key>}{<word>}--- キーとワードによる発生頻度
$freqkeys{<word>}--- ワードのみの発生頻度
27-28:前後5つ分アクセスできるようにNULLデータの入った@Xを使っているため、
不必要なNULLデータを削除。
31-40:カンマで区切られた形式で出力
変数いじってるので、このままじゃ走らないです。デバッグ必要です。課題だとすると、マルマル回答では気が引けるから(^^;がんばれー!
この回答への補足
連想配列で処理が早くできるようになりました。
少し内容が変わっていますが、非常に参考になりました。
ありがとうございます。
open(IN, "kai.dat");
chomp(@aa = <IN>);
close(IN);
open(DATA,"thab.dat");
chomp(@bb = <DATA>);
close(DATA);
$" = ",";
foreach $x (@aa){
@categ = split(/,/, $x);
push(@hyper,$categ[0]);
for $m(1 .. @categ-1){
foreach $y (@bb) {
if($y =~ /\|$categ[$m]\|(を|に|か|ら|と|へ|まで|より|の)\|/){
@ato=split(/\|/,$');
if (($ato[0] =~ "n") || ($ato[0] =~ "d") || ($ato[0] =~ "k")){
if (&minfo($categ[$m],$ato[0]) > 15.00){
$freqkeys{$categ[0]}{$ato[0]}++;
$freqword{$ato[0]}++;
}
}
}
}
}
@words = keys %freqword;
print "word=@words\n";
foreach $hyp ( @hyper ){
print "$hyp,";
foreach $sub ( @words ) {
$f = $freqkeys{$hyp}{$sub};
print "$f,";
}
print "\n";
}
}
非常に勉強になりました。ありがとうございます。
22: $freqkeys{$k}{$w}++;
23: $frepword{$w}++;
は配列番号の代わりにキーワードを利用する方法だと認識しました。
自分で配列にpushする方法を試したみたのですが
とても時間がかかりましたので、この方法を試してみたいと思います。
進捗があれば、報告させてください。
よろしくお願いいたします。
No.1
- 回答日時:
1. fileBを読んで、|でsplitして、1語を1行で出力。
2. 1.の出力を1行ずつ読んで、サイズが10の配列にpush。6番目の要素がfileAの語だったら、前後の5要素を、それぞれ出力。次の行のために、先頭の要素を配列からshiftしてループ。
3. 得られた出力をExcelに食わせてピボットテーブルで整形。
UNIX系で数だけ知りたいなら、sort|uniq -cとか。
――みたいに、問題を分割して、解決しやすい形にならないか考えてみては。
アドバイスありがとうございます。
ただ、ファイルが非常に大きいので
エクセルでは処理しきれない状況です。
問題を細分化する方法で一つ一つ進めたいと思います。
ありがとうございました。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- レシピ・食事 今一人暮らしなので節約のため1週間分の食材を買い 1週間で食べ切れる料理を作って毎日同じものを食べて 6 2023/03/27 09:49
- 赤ちゃん 離乳食を始めた赤ちゃんのうんちについて。 生後7ヶ月です。 今まで離乳食をほとんど食べてくれなかった 1 2022/07/28 18:11
- 食生活・栄養管理 回復期に望ましい食生活とは? 病気の回復期に望ましい食生活を教えてください。詳細は下記の通りです。 1 2022/07/10 12:44
- 赤ちゃん 生後9ヶ月、ミルクは必要? 朝昼晩+おやつ2回あげてます。 量的には、昨日の献立の場合↓のような感じ 2 2022/09/28 13:41
- 食べ物・食材 野菜の値段はいくらか 8 2023/03/16 21:55
- 食生活・栄養管理 食生活チェックお願いします! 半年ほど寝たきり、ほとんど食べられないという大病を患い、いま回復期です 3 2022/07/18 15:06
- 食生活・栄養管理 しゃぶしゃぶ食べ放題で胃腸の調子が悪くなりました。以下の野菜を丸呑み、水で流し込みをたくさんしたのと 3 2023/04/02 04:16
- 哲学 アマテラス種族・国家公民人種と呼ぶべきお二階さんというようなありかたは 本質か? 70 2022/12/19 04:42
- 食生活・栄養管理 野菜を全く食べない人が取るサプリ 4 2023/08/06 21:56
- 婚活 料理力が全くない 10 2022/06/03 10:25
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
awkスクリプトでダブルクォーテ...
-
DOSコマンドで、標準出力を出力...
-
ファイル出力の改行コードをLFに
-
[Perl]ファイル出力のエンコー...
-
エクセルVBAで素数だけを出力す...
-
文字コードの変換(Shift-JISか...
-
至急お願いします。C言語で.img...
-
Perlでファイルの末尾から指定...
-
perlでの文字列抽出
-
重複するデータを抽出できる秀...
-
Active Perlでsleepを使う。
-
文章を一文一文として処理する...
-
sprintfで10進数を桁数指定で16...
-
perlでcsvの出力について
-
MAC OSXのTerminalにperlの出力...
-
log2の「正確な」計算方法
-
VBAでCSVファイルの特定行を書...
-
VBAでCSVファイルを途中行まで...
-
batファイルでrenameができませ...
-
ExcelをCSV書き出す場合のシー...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
awkスクリプトでダブルクォーテ...
-
エクセルVBAで素数だけを出力す...
-
sprintfについて
-
教えて!perlから.exeファイル...
-
重複するデータを抽出できる秀...
-
log2の「正確な」計算方法
-
DOSコマンドで、標準出力を出力...
-
文字コードの変換(Shift-JISか...
-
perlでの文字列抽出
-
至急お願いします。C言語で.img...
-
ダイアモンド演算子<>に対するb...
-
コマンドプロンプトで行が見え...
-
Perlで着メロDLカウント
-
perlのpushについてです。
-
perlでcsvの出力について
-
ドメインからIPアドレスあるい...
-
MySQLに画像を格納してperlで取...
-
htmlから、ファイル、もしくはC...
-
MAC OSXのTerminalにperlの出力...
-
perlでcsvの指定フィールドに書...
おすすめ情報