• ベストアンサー

perlのプログラムで一部分からないところがあります

下記のプログラムを書いたのですが一部分かりません。 どなたか、教えていただけないでしょうか? 宜しくお願い致します。 @array = qw( いくら いくら いくら あたご くじら あたご いくら あたご ); #重複配列を削除する。 undef(%count); @array = grep(!$count{$_}++, @array); #出現頻度の低い順で並べ替える。 ★この部分がどうしても分かりません。★ #表示させる print @array; --表示されたもの---- くじら あたご いくら

  • Perl
  • 回答数1
  • ありがとう数1

質問者が選んだベストアンサー

  • ベストアンサー
  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.1

元データと求める結果からすればやり方はほかにもありますが、 提示されているスクリプトを活かすならこう? use strict; use warnings; my @array = qw( いくら いくら いくら あたご くじら あたご いくら あたご ); #重複配列を削除する。 my %count; my @greped_array = grep {!$count{$_}++} @array; #元データ print join("\n", @array), "\n"; print "#####\n"; #カウントつき printf "%2d: %s\n", $count{$_}, $_ for @greped_array; #出現頻度の低い順で並べ替える。 print "######\n"; my @sorted_array = sort {$count{$a} <=> $count{$b}} @greped_array; printf "%2d: %s\n", $count{$_}, $_ for @sorted_array; 要は %count のデータにしたがって(重複を取り除いた)配列をソートして やればよいのではないでしょうか。わかりやすくするために 出力を段階を踏んで行ってみました。

ayaka19801201
質問者

お礼

非常にすばやい、回答いただきありがとうございます。 動作確認もばっちりでした。 また、非常に分かりやすく書いていただき、本当に、 ありがとうございます。 とても、勉強になります!

関連するQ&A

  • perl初心者ですが、プログラム作成で行き詰ってしまいました。

    perl初心者ですが、プログラム作成で行き詰ってしまいました。 参考書を読みあさり、色々とググってみたのですが、どうしても組み立てられません。知識のある方ご回答よろしくお願いします。 一つ目は: 英語の文章を記憶したファイルを指定し,その内容を読み込み,文章内に含まれる単語を出現頻度の降順で表示させるプログラムを作成すること 「1位:・・・(・・回)」 「2位:・・・(・・回)」 ... なお,一つの単語が二行にまたがることはないものとする。 二つ目は: テストの成績データを記憶したCSV ファイルを指定し,その内容を読み込み,各学生の総合点と順位,各科目の最高点,最低点,平均点を記憶したCSVファイルを書き出すプログラムを作成せよ。 なお,入力用のファイルと出力用のファイルはキーボード入力で指定するものとする。 また,異なる学生数および科目数のCSV ファイルを読み込んでも正しく動作するようにすること。 卒業のかかったレポートで、この二つを完成させないと先に進めないのです。 本当に図々しい質問で大変申し訳ありません。知識のある方どうかご教授ねがいます。 *ひとつめに関しては: open (FILE, 'perl.txt') or die "$!"; while (my @array = <FILE>){ foreach (@array) { $count{ $_ }++ ; } @rank = sort { $count{ $b } <=> $count{ $a } } keys %count ; foreach (0..$#rank) { $kagi = $rank[ $_ ]; $kaisu = $count{ $kagi } ; print $_+1, "位:$kagi($kaisu 回)\n" ; } } のように書いたところで行き詰ってしまいました。 二つ目は: open (FILE, 'data.txt') chomp(@data = <FILE>) ; $i= 1 ; # 行番号を記憶する変数 for (@data) { # 各行に対して以下を繰り返す. # 各行の数値を配列の要素として記憶する. @list = split(/,/, $_) ; # サブルーチンを呼び出して,結果を表示 print "$i行目:" ; print "数値:",&cardinality(@list),"個," ; print "最大値:",&maximum(@list),"," ; print "最少値:",&minimum(@list),"," ; print "合計:",&summation(@list),"," ; print "平均:",&average(@list),"\n" ; # 行番号の更新 $i++ ; } とまで書き、もう何が何だか訳わからなくなってしまいました。

    • ベストアンサー
    • Perl
  • perlの引数が不安定になります。

    perlの引数が不安定になります。 具体的には、 同じ値が返されるはずなのに、返されません。 私の持っている、入門用の本を調べたのですが全くわかりません・・・ 分かる方、教えていただけないでしょうか。 宜しくお願い致します。 open IN, 'Testfile.txt'; #Testfile.txtは、ある程度の大きさがあったほうが良いと思うので、ヤフーのトップページのソース全てなどが適当かもしれません。 my @array = <IN>; close IN; my $count = "1"; print &test(@array,$count); #何も表示されない print "<HR>"; print &test2($count,@array); #1が表示される。 sub test() { my (@array,$count) = @_; return $count; } sub test2() { my ($count,@array) = @_; return $count; }

    • ベストアンサー
    • Perl
  • Perlで重複行を削除したい

    あ b c d e e g あ b c d e e g い b c d e e g い c c d e e g 上記のようなCSVデータ(タブ区切り)が100行くらいあるのですが、1列目にある、あ、あ、い、いは無視して、2列目以降のデータのみで重複を比較して同じ行は削除したいのですがどのようにすればよいでしょうか? 下記コードを応用すれば分かりそうなのですが、自分で作ることができませんでした。 どなたか、教えていただけ無いでしょうか? 宜しくお願い致します。 open(OUT, "$file"); @array = <OUT>; close(OUT); my %count; @array = grep(!$count{$_}++, @array); print @array;

    • ベストアンサー
    • CGI
  • 空の配列を削除して、詰めていく。

    データベースから値を取ってくるとき、全て、同じ値が入ってくる場合があります。 $a = array(100,100,100,100,100)というような。 これを、array_uniqueで重複している値を削除したのですが、その際、print_rで見ると、 Array ( [4] => 100 ) と表示されました。つまり、キーが0ではなく、4となってしまっています。 array_uniqueで帰ってきた値が複数なら、さらにsortすることで0から始まる配列として並び替えられるのですが、1つしか帰ってこないとsortをしても、キーは変わらないようです。 この値を表示させるとき、countで配列の数を数え、さらにfor文でcountの数だけ回し、print $i;で表示させるようにしているのですが、上記のようにarray_uniqueで1つの値しか帰ってこないと、ページに値がきちんと表示できなくなってしまいます。 これを解決するために、空の要素を削除して、空白でない要素のキーを前に詰めてくれるような関数などを探しているのですが、何か方法などありますでしょうか? Array ( [4] => 100 ) が Array ( [0] => 100 )となるようにしたいのです。 よろしくお願いいたします。

    • 締切済み
    • PHP
  • perlで配列を複数行削除したいのですが

    @UserDataNum=qw(11 13 34) @PDataLinesの中身 1<>タイトル<>2009/02/10<>適当なデータ<>適当なデータ2<> 2<>タイトル2<>2009/03/13<>適当なデータ<>適当なデータ2<> .. 50<>タイトル3<>2009/03/23<>適当なデータ<>適当なデータ2<> $TODAY=今日の時間; foreach(0..$#PDataLines){ my@aaa= split(/<>/,$PDataLines[$_]); my$a2 = $aaa[2];$a2 =~s{/}{}g; #ここの処理で@UserDataNumに入っている数字と一致する$aaa[0]を含む行を除外し、時間が今日以降のものを配列@Arrayに入れたいのです if(($aaa[0] !~ /@UserDataNum/) && ( $TODAY < $a2)){ push(@Array,$PDataLines[$_]); } } print "\@Array=@Array"; if(grep(!/@UserDataNum/, @PDataLines) && ( $TODAY2 < $a2)){ としてみたり試みているのですが、思うように出来ずにいます。 どなた様かご教授願えませんでしょうか 宜しくお願い致します。

    • ベストアンサー
    • Perl
  • 配列操作

    お世話になっております。適切なタイトルが分からず、漠然と「配列操作」となっていることをお詫びいたします。 ところで、アドバイス頂きたい内容とは、長文のテキストから、単語単位、かつその出現回数を配列にまとめたものがあります。 こんな感じ print_r($result);とすると、 Array ( [対策] => 61 [クランク] => 32 [表示] => 25 [て] => 24 [サイト] => 24 [運営] => 21 [テクニック] => 18 [ため] => 15 [徹底] => 14 ) また、別のテキストから同じように単語単位、出現回数を配列にまとめた$result2というものがあるのですが、そもそも別のテキストを分析?したものなので単語も出現回数もバラバラです。 $result2 Array ( [教えて] => 61 [PHP] => 32 [運営] => 25 [CGI] => 24 [html] => 24 [桜] => 21 [表示] => 18 [PEAR] => 15 [http] => 14 ) そこで、今回質問したいのは、最初の配列をそのまま出現頻度の多い順に表示させ、その横に$result2を表示させたいのですが、内容を比較したく同じ単語のみ以下のように表示させたいのですが思うような結果を得られずにいる次第です。 お忙しい中恐縮ですが、アドバイスのほど頂戴できれば幸いです。宜しくお願いいたします。 上の配列を例にしています。 対策61 クランク32 表示25     表示18 て24 サイト24 運営21     運営25 テクニック18 ため15 徹底14

    • ベストアンサー
    • PHP
  • Perlのデータ構造について

    Perlのデータ構造でわからないところがあります。 ハッシュの配列で、以下の構造がある場合 my %hash_array = ( 1=>["aaa", "bbb"], 2=>["ccc", "ddd", "eee"], 3=>[], 4=>["fff"] ); print $hash_array{1}[0]; # aaaが表示される。 print $hash_array{2}[2]; # eeeが表示される。 ですが、 $hash_array{1}は 2 $hash_array{2}は 3 $hash_array{3}は 0 $hash_array{4}は 1 のように個数を表示させるのは、どうすればよいでしょうか? Perlのデータ構造に詳しいサイトや書籍はありますか? また、Perl 5.6.1から Perl 5.8.7に乗りかえようとしていますが、 データ構造など大幅に変わった点はあるのでしょうか?

    • ベストアンサー
    • Perl
  • smartyのforeachの使い方がよくわかりません。

    Smartyを使ってサイトを作っていて連想配列でネストしている配列を{section}でループさせています。 はじめの配列はうまく取り出せてループできるのですが、ネストした配列の中身を取得して表示させることができません。{section}内でさらに配列の要素をループさせたい場合どのようにしたらよいのでしょうか? print_rの結果はこんな感じです。[test] => Arrayの配列を取り出したいのですがどのようにしたらよいでしょうか? Array ( [0] => Array ( [id] => 7 [postdate] => 2008/02/21/ 06:48:10 [count] => 0 [test] => Array ( [0] => Array ( [id] => 4 [title] => あああああああああ) [1] => Array ( [topicid] => 6 [postdate] => 2008/02/19/ 13:44:41

    • 締切済み
    • PHP
  • 配列中のあるキー、値を取得して、それを変更したい

    やりたいことは、 $hoge = array ( 0 => '1', 1 => '2', 2 => '3', 3 => '3', 4 => '3' ); のような配列があったとします。 この配列の値の出現頻度を調べて、 $hoge_syutugen_hindo = array_count_values($hoge); print_r($hoge_syutugen_hindo); $hoge_syutugen_hindoの結果 Array ( [1] => 1 [2] => 1 [3] => 3 ) $hoge_syutugen_hindoの結果で[3]の出現頻度が3回以上あったら、 Array ( [1] => 1 [2] => 1 [3] => 3 ) を Array ( [1] => 1 [2] => 1 [4] => 1 ) に変更。 少ない場合は Array ( [1] => 1 [2] => 1 [3] => 2 ) を Array ( [1] => 1 [2] => 1 [3] => 2 ) そのままの配列を返したいのです。 $hogeの配列の値には必ずしも1や2が含まれるわけではありません。 $hoge = array ( 0 => '3', 1 => '3', 2 => '3' ); や$hoge = array ( 0 => '1', 1 => '3', 2 => '3', 3 => '3' ); のようなパターン等もあります。 わたしなりに下記のようなスクリプトを作成しましたが、 $arr_pattern = '/^(3\s=>\s)[3-99]$|^(3=>)[3-99]$|^(3=>\s)[3-99]$|^(3\s=>)[3-99]$|^(3\s=>\s)\'[3-99]\'$|^(3=>)\'[3-99]\'$|^(3=>\s)\'[3-99]\'$|^(3\s=>)\'[3-99]\'$|^(\[3\]\s=>\s)[3-99]$|^(\[3\]=>)[3-99]$|^(\[3\]=>\s)[3-99]$|^(\[3\]\s=>)[3-99]$|^(\[3\]\s=>\s)\'[3-99]\'$|^(\[3\]=>)\'[3-99]\'$|^(\[3\]=>\s)\'[3-99]\'$|^(\[3\]\s=>)\'[3-99]\'$/'; reset($deliyery_kind_syutu); while(list($k, $v) = each($deliyery_kind_syutu)) { $kv = "$k=>$v"; if(preg_match($arr_pattern, $kv)){ $new_hkv = preg_replace($arr_pattern,'4 => 1', $kv); $n = count($deliyery_kind_syutu); for($i=0; $i<$n; $i++){ $new_array[] = ($deliyery_kind_syutu[$i]); } $new_array[] = $new_hkv; } } array ( 0 => NULL, 1 => 1, 2 => 1, 3 => '4 => 1', )となり、array(1 => 1, 2 => 1, 4 => 1)のような結果になりませんでした。 分かる方が見えましたらご教授ください。

    • ベストアンサー
    • PHP
  • 配列にきちんと入れる方法

    txtの行数字が合っている数字だけ(7.6.4.1)抜いて上から順に配列に入れたいのですが、何か微妙に違う結果になります。 7 7 10 7 6 6 4 4 5 4 9 4 1 1 2 1 $abc=file("1.txt"); for($l=0;$l<count($abc);$l++){ $def=explode("\t",$abc[$l]); if($def[0]==$def[1]){ $ll=array($def[0]); print_r($ll); }} Array ( [0] => 7 [1] => 6 [2] => 4 [3] => 1 ) 上記のようなブラウザ結果にしたいのですが、別々に配列が表示されてしまいます。どう記述すればこの結果になるでしょうか?ご教授ください。

    • ベストアンサー
    • PHP