以前お世話になったyamと申します。どうぞよろしくお願いします。
あるファイルから、複数の文字列をランダムに抽出したいと思い、いろいろ調べていたところ、
以下のホームページに行き当たりました。
http://chaichan.web.infoseek.co.jp/qa6500/qa6619.htm
このページを参考にすれば、自分がやりたいことができるのではないかと思いました。
私がやりたいことはあるファイルの中に、以下のような「。」で改行された文字列が1000あります。
その中から重複せずに100の文字列を抽出したいです。
------------------------------
おはようございます。
こんにちは。
こんばんは。
さようなら。
今日は、いい天気ですね。
じゃ、また会いましょう。
………
------------------------------
そこで、先のページを参考にしてプログラムを書いてみたのですが、どうしてもいくつかの文字列が重複してしまいます。
よろしければ重複せずに抽出する方法を、お教え頂けないでしょうか。
何卒よろしくお願い致します。
perlで複数の文字列をランダムに抽出
Re: perlで複数の文字列をランダムに抽出
おはようございます。
トントンです。
仕様が一部わからないので下記部分だけ。
>よろしければ重複せずに抽出する方法
参考になれば良いのですが。
# ちなみにnext if($a == $_) って 行番号比較ですか?
トントンです。
use strict;
open my $in, "<C:/in.txt" or die "not found\n";
my @all = <$in>;
my @lines;
my @tmp;
my %rep;
die "input text is insufficient\n" if(@all < 10);
foreach (0..9) {
my $index = int(rand(@all - 1));
push(@tmp, $all[$index]);
}
@lines = grep {++$rep{$_} < 2} (@tmp, @tmp);
>よろしければ重複せずに抽出する方法
参考になれば良いのですが。
# ちなみにnext if($a == $_) って 行番号比較ですか?
Re: perlで複数の文字列をランダムに抽出
トントンさん
こんにちは、yamです。
まずはわざわざお返事頂き、ありがとうございます。
> 仕様が一部わからないので
言語仕様については私もわかりませんでした。
私はPerlも含めプログラムを勉強し始めたばかりなので、理解が浅いことも確かですが、
「$#」などの書き方について疑問を持ちました。そして調べてはみたのですが、
結局のところ、わかりませんでした。
> 下記部分だけ。
>> よろしければ重複せずに抽出する方法
まずはランダムに10の文字列を抽出する方法をお示しくださったのですね。
勉強させて頂きます。ありがとうございました。
(なお、実際に動かせて頂きましたが、確かに重複することなく文字列を抽出することができました。ありがとうございます!)
ただ、上に示させて頂いたホームページで「これはいいなぁ」と思ったのは、行数が指定できる点と、取得した行数を最後に取得している点でした。
このような形で書くことはできないでしょうか。再度ながら、皆様、何卒よろしくお願い致します。
PS
> # ちなみにnext if($a == $_) って 行番号比較ですか?
そうだと思います。そうだと思いますなんて、無責任な表現ですが (^_^; 先ほどのページにもそのように記されておりました。
for(@line){next if($a==$_);} #重複していたら、次のループへ
取得した行が重複しているのが問題でしたので、私もここらあたりをいろいろ変更してはみたのですが、結局のところどうしていいかわからず、皆様に質問させていただきました。
こんにちは、yamです。
まずはわざわざお返事頂き、ありがとうございます。
> 仕様が一部わからないので
言語仕様については私もわかりませんでした。
私はPerlも含めプログラムを勉強し始めたばかりなので、理解が浅いことも確かですが、
「$#」などの書き方について疑問を持ちました。そして調べてはみたのですが、
結局のところ、わかりませんでした。
> 下記部分だけ。
>> よろしければ重複せずに抽出する方法
まずはランダムに10の文字列を抽出する方法をお示しくださったのですね。
勉強させて頂きます。ありがとうございました。
(なお、実際に動かせて頂きましたが、確かに重複することなく文字列を抽出することができました。ありがとうございます!)
ただ、上に示させて頂いたホームページで「これはいいなぁ」と思ったのは、行数が指定できる点と、取得した行数を最後に取得している点でした。
このような形で書くことはできないでしょうか。再度ながら、皆様、何卒よろしくお願い致します。
PS
> # ちなみにnext if($a == $_) って 行番号比較ですか?
そうだと思います。そうだと思いますなんて、無責任な表現ですが (^_^; 先ほどのページにもそのように記されておりました。
for(@line){next if($a==$_);} #重複していたら、次のループへ
取得した行が重複しているのが問題でしたので、私もここらあたりをいろいろ変更してはみたのですが、結局のところどうしていいかわからず、皆様に質問させていただきました。
Re: perlで複数の文字列をランダムに抽出
ここのnextはwhileの次のループを期待してのことでしょうけど、実際はこのforの次のループに移行するのでまったく意味のないコードになってしまっています。yam さんが書きました:for(@line){next if($a==$_);} #重複していたら、次のループへ
while(@line < $num){ # -1不要
$a = int(rand(@all)); # +1不要
$c = 0;
for(@line){
++$c if($a == $_); # 重複してたらカウント
}
push(@line, $a) if($c < 1); # カウントされなかったらOK
}
for(@line){ print OUT ($_+1).":".$all[$_]; } # テキストの行数は1からはじまるようにした
$c = 0;
@all = map(++$c.":".$_, @all);
while(@line < $num){
$a = int(rand(@all));
push(@line, $all[$a]);
splice(@all, $a, 1);
}
for(@line){ print OUT $_; }
print OUT~の箇所の構文エラー(ブロックの付け忘れ)を修正しました。
最後に編集したユーザー ISLe on 2011年5月23日(月) 21:42 [ 編集 1 回目 ]
Re: perlで複数の文字列をランダムに抽出
ISLeさん
yamです。以前もお教え頂きましたが、この度もいろいろお教え頂き、
本当に感謝しております。ありがとうございます。
また詳しい解説も頂いたため、どうしてうまくいかなかったのか、その原因もよくわかりました。
とても勉強になりました。ありがとうございました。
また、
この箇所についても本当に勉強になりました。ありがとうございました。
それに、もう一つお書きくださったスクリプトについても、参考にさせて頂きました。
最初にカウンタをリセットしておいて、そして1行ずつ番号を付けるという方法ですね(その後読み込み)。
おっしゃる通り、こんな方法もあることはわかるのですが、ご指摘されるまで全く気が付きませんでした。
(本当に勉強になりました!)
ISLeさんには前回もお助けくださいましたが、今回もお助けくださったこと、本当に感謝しております。
そして本当に良い勉強ができました。ありがとうございました。
yam
PS
どちらのスクリプトも print のところにエラーが出るのですが、
for(@line) をいちばん後ろに持って行くことで回避されました。
yamです。以前もお教え頂きましたが、この度もいろいろお教え頂き、
本当に感謝しております。ありがとうございます。
また詳しい解説も頂いたため、どうしてうまくいかなかったのか、その原因もよくわかりました。
とても勉強になりました。ありがとうございました。
なるほど、そうだったのですね。このご指摘、目から鱗が落ちる思いでした!ISLe さんが書きました: ここのnextはwhileの次のループを期待してのことでしょうけど、
実際はこのforの次のループに移行するのでまったく意味のないコードになってしまっています。
また、
$c = 0;
for(@line){
++$c if($a == $_); # 重複してたらカウント
}
push(@line, $a) if($c < 1); # カウントされなかったらOK
それに、もう一つお書きくださったスクリプトについても、参考にさせて頂きました。
最初にカウンタをリセットしておいて、そして1行ずつ番号を付けるという方法ですね(その後読み込み)。
おっしゃる通り、こんな方法もあることはわかるのですが、ご指摘されるまで全く気が付きませんでした。
(本当に勉強になりました!)
ISLeさんには前回もお助けくださいましたが、今回もお助けくださったこと、本当に感謝しております。
そして本当に良い勉強ができました。ありがとうございました。
yam
PS
どちらのスクリプトも print のところにエラーが出るのですが、
for(@line) をいちばん後ろに持って行くことで回避されました。