アプリ版:「スタンプのみでお礼する」機能のリリースについて

perlでデータを並び替えて整理したいです。
【元データ】
A a b
A c d
A e f
A g h
B i j
B k l
B m n
C o p
C q r
C s t
C u v



上記のデータを下記のように並び替えしたいのですが上手くできずに困っています。
どのような記述をすれば良いのでしょうか。間の空白はタブ区切りです。
【目標】
A a b c d e f g h
B i j k l m n
C o p q r s t u v
D



現在、元データから

A
B
C
D


というデータを作り、元データと比較していますが上手くいきません。
for($i=0; $i<@key; $i++){
print OUT "$key[$i]";
for($j=0; $j<@data; $j++){
if($key[$i] =~ /$data[$j]/){    #部分一致
print OUT "$'";
}
}
print OUT "\n";
}


部分一致の行を正規表現を用いて上手く処理したいのですがやり方がわからず躓いています。
宜しくお願いします。

A 回答 (4件)

「うまくいかない」とはどのような状態でしょう?


その分析から始めるのがプログラミングのコツです。

if($key[$i] =~ /$data[$j]/){

これだと、
・行の途中に $data[$j] がある場合でもマッチする。
・ $key[$i]が検索対象。 $data[$j] を探す
・$data[$j]内に正規表現のメタ文字等が入っていると、文字検索ではなく正規表現検索になる
という問題があります。
うまくいかないのは、これらの複合では?

この回答への補足

回答ありがとうございます。
言葉足らずで申し訳ありません。

@key=A
    B
    C
    ・
    ・
@data=元データ
と設定し、
OUTに出力する。
1.@keyのAをOUTに出力
2.for文を用いて@keyのAと、@dataのAを比較。
@keyのAと@dataのAが一致した時、@dataのAの行をOUTに抜き出す(Aの右側の部分のみ)。この繰り返しで@dataのAの行の右側部分を
OUTに全て出力する。
3.改行する
4.1と同様に@keyのBをOUTに出力 以下同様の操作

という操作を行いたいと考えています。
$key[$i]が $data[$j]の頭の部分(例:A)と一致する場合に$data[$j]の後ろの部分(例:a b)を抜き出したいのですが、この場合にメタ文字をどのようにif文に組み込めば良いかというところがわかりません。


・行の途中に $data[$j] がある場合でもマッチする。
→@keyのA,B,C..は@dataの頭の部分にしかないので
 行の途中で一致するということは無いと思います。
・$data[$j]内に正規表現のメタ文字等が入っていると、文字検索ではなく正規表現検索になる
→a b等の間にタブが入っているので正規表現検索になっているということでしょうか?
kmeeさんのおっしゃる通りこれらの複合ができてないのだと思います。

補足日時:2012/10/17 01:24
    • good
    • 0

いまいち正確な仕様がわからないので・・・


一番最初の文字をキーに並び替えを行うということで書いてみたのですが

大きな流れは、こんな感じ。
ファイルに書いてあるデータを読み込む。
1行ずつ受け取りタブでsplitする。
最初の文字をキーに配列に残りデータをpushする

出力。
おしまい。


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

#データの記載されたファイルを開く
open my $fh, "<", "hoge.txt" or die $!;

my (%hash, @data);
while (my $line = <$fh>) {
chomp($line); #行末の改行コードを削除する

#1.tabで分割
@data = split(/\t/, $line);

#2.ハッシュに、最初の文字をキーに。値を配列のリファレンスとみなし
# 2番目の要素から最後の要素を配列のスライスとしてpushする
push @{$hash{$data[0]}}, @data[1, -1];
}

close $fh or die $!;

#3.出力
for my $key (sort keys %hash){
#最初の文字(大文字のアルファベット)と残りを配列として扱い tabでjoinして出力
print join("\t", ($key, @{$hash{$key}})), "\n";
}
    • good
    • 0
この回答へのお礼

目標とするファイルの作成ができました。
丁寧な説明までつけて頂き有難うございました。

お礼日時:2012/10/17 16:13

@keyと@dataがそれだとすると



> ・ $key[$i]が検索対象。 $data[$j] を探す

と書いたように
「"A"の中に"A a b"にマッチする箇所があるか探す」
ことになります。見つかるわけがありません。
    • good
    • 0
この回答へのお礼

回答有り難うございます。
基本的な理解が不十分でした。
正規表現及びメタ文字についてもう少し調べてみます。

お礼日時:2012/10/17 16:22

#2 を勝手に改造する試み:



まず @data は while の中でしか使っていないので my の位置を移動する. ついでに分割するときに
my ($key, @data) = split /\t/, $line;
とすればそのあとが
push @{$hash{$key}}, @data;
と短くなる.
    • good
    • 0
この回答へのお礼

効率良くするための試みですね。
勉強になります。

お礼日時:2012/10/17 16:19

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