プロが教えるわが家の防犯対策術!

毎度お世話になっております。
今夜も躓いてしまってどうにもならないので、お力をお貸しいただけませんでしょうか。


以下のようなリストファイルがあります。
------------------
項目1
項目2
・・・
------------------

このリストにマッチした行を、リストの項目ごとにランダムに3行選んで出力したいです。
マッチした行を取り出すところまでは、以下のような形でできたのですが、
ここから先をどのように書けばいいのかわかりません。

------------------
my $list = 'リストファイル';
open (IN, "$list");
my %l;
while(<IN>) {
chomp;
$l{$_}++;
}
close IN;

while(<DATA>) {
my ($xx,$yy) = split(/\t/,$_);
if (exists($l{$xx})) {
# print;
# ここから先がわかりません
}
}
__END__
項目1 N1
項目1 N2
項目2 N3
項目2 N4
項目2 N5
項目1 N6
項目2 N7
項目2 N8
項目2 N9
項目1 N10
------------------

以下のような出力結果にしたいです。
------------------
項目1 N2
項目1 N6
項目1 N10
項目2 N3
項目2 N5
項目2 N9
------------------


どうぞよろしくお願いいたします。

A 回答 (3件)

「特定の項目を持つ配列」を作るには、別に split して連想配列にしなくても、


配列の要素から目的の条件に合う要素を抽出する grep を使えば1行で書けます。

あらすじはこんな感じ

my @items = <IN>;# (この行の上下のopen/closeは記述省略)
my @data = <DATA>;# 両方一気に読み込んじゃうことの是非は置いとく

map {
chomp;# 改行がついたままなので削る
my $pat = $_;# grep の中で $_ が使われるので別の変数にコピる
my @line = grep(/^$pat/, @data);# ここでマッチする行を抽出
# ここで回答 No.1 への補足にある、ランダム出力のループを使う
} @items;

# "map", "foreach (@items)", "while (<IN>)" のどれが好みかは置いとく
    • good
    • 0
この回答へのお礼

お礼が遅くなってすみません。
勉強になりました!ありがとうございます。

お礼日時:2011/12/11 10:17

「ある配列からランダムに 3個の要素を表示する」ことはできるんだよね.



だとしたら, 「特定の項目を持つ配列」を作ればいい.

つまり, 今のプログラムとは逆に先にデータを読み込んで, 「リストファイル」からはあとで入力する.
    • good
    • 0
この回答へのお礼

お礼が遅くなってすみません。
勉強になりました!ありがとうございます。

お礼日時:2011/12/11 10:17

「マッチする」かどうかはとりあえず脇に置いて, 「ファイルの内容をランダムに 3行表示する」ことはできますか?

この回答への補足

以下のように書いて、「ファイルの内容をランダムに 3行表示する」ことは一応できたのですが、
「項目ごとにランダムに 3行」がどうやったらいいのかわかりません・・・。

--------------------
@line = <DATA>;
for ($i = 0; $i < 3; $i++) {
$r = int(rand(@line));
$s = splice(@line,$r,1);
print $s;
}
__END__
項目1 N1
項目1 N2
項目2 N3
項目2 N4
項目2 N5
項目1 N6
項目2 N7
項目2 N8
項目2 N9
項目1 N10
--------------------

補足日時:2011/12/04 10:02
    • good
    • 0

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