• ベストアンサー

重複する値を表示しない

以下のようなデータ(CSV)があったとします。 1020,大森,3249 1023,高橋,3252 1020,大森,3249 ここで1020が重複しているので重複させないように printしたいと考えています。ほかにも多数のデータ が重複しているかも知れない。 本を見て、ハッシュのキーは重複しない ことを利用して foreach (@man){ $H{$_}=1; #値は無視しキーにセット } @man = keys %H;  #ハッシュキーを配列へ foreach $eachman (@man) { ($num, $name, $encpass) = split(/,/, $eachman); print ・・・・ ・・・・ のように作ってみましたが、重複されて 表示されます。順番のみ変わっていました。 このような感じで簡単にできる方法がありましたら 教えてください。

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

  • ベストアンサー
  • kapura
  • ベストアンサー率50% (48/95)
回答No.3

質問を勘違いしているかもしれませんが、%H or %tmpを活かせばもっとシンプルになると思います。 my %tmp; while (<DATA>) {   chomp;   my ($num, $name, $encpass) = split /,/;   if (!$tmp{$num}++) {     print "$num:$name\n";   } } __END__ 1020,大森,3249 1021,塚本,3250 1022,播磨,3251 1023,高橋,3252 1024,周防,3253 1025,沢近,3254 1023,高橋,3252 1020,大森,3249 1023,高橋,3252 1024,周防,3253

参考URL:
http://www.meibin.net/reference/books/perl2/cookbook/ch04_07.htm
ma_trix
質問者

お礼

回答ありがとうございました。 while (<DATA>) を使う方法ですが、どうして止まるか原因がわかりました。 別ルーチンでopen TXT 、・・・みたいなことをやって配列にTXTの内容を入れてしまっています。 while(<>)<>の部分が配列ではダメなんですよね?試してみましたがダメでした。

すると、全ての回答が全文表示されます。

その他の回答 (3)

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

> while(<>)<>の部分が配列ではダメなんですよね?試してみましたがダメでした。 配列に対してその要素を列挙しつつ操作をするのなら for $var (@arrary) または foreach $var (@array) を使います。 $var は省略できて、その場合は $_ で各要素が参照できます。 あと念のため解説しておきますが、DATAというファイルハンドルは openしないでも使うことができて、どこからデータを持ってくるのかというと、 スクリプトの末尾、__END__の後におかれた行です。

ma_trix
質問者

お礼

回答ありがとうございました。 理解しようと試みましたが、ダメでしたので締め切ることにしました。パールって奥が深いですね。

すると、全ての回答が全文表示されます。
  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.2

> whileの文があると途中で処理が終わっちゃうみたいでHTMLが最後まで表示されない現象が起こりました。 これはなにやらよくわかりませんが、 > ただ、データが完全一致していないと重複チェックが消えないようで、 > 1列目をキーにできればいいのですが、その方法はあるでしょうか? ということであれば、 foreach (@man){  $H{$_}=1; } このループを foreach (@man){  my $num;  ($num, undef) = split(/,/, $_, 2);  $H{$num}=$_; } としてやって、 foreach $eachman (sort keys %H) {  ($num, $name, $encpass) = split(/,/, $H{$eachman}); でどうでしょう? この場合先頭のエントリが同じものは最後に登場したものが有効になります。 2回同じ文字でsplitするのはいやらしいですが、わかりやすさを優先ということで。

ma_trix
質問者

お礼

回答ありがとうございました。 おかげさまで出来ました。2回Splitするのは改善できればいいですけど、私には無理そうですが、勉強してみます。

すると、全ての回答が全文表示されます。
  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.1

基本的な考え方は間違ってはいないと思います。 試しに提示されたコード片を元にスクリプトを組んでみましたが正しく動いています。 ハッシュにためたデータを配列に書き戻してますけど、 似たような別の名前の変数に入れちゃってるなんてことは ありませんか? use strict; use warnings; my %tmp; my @table; while (<DATA>) {   chomp;   push @table, $_; } foreach (@table){   $tmp{$_} = 1; } foreach my $entry (sort keys %tmp) {   my ($num, $name, $encpass) = split(/,/, $entry, 3);   print "$num:$name\n"; } __END__ 1020,大森,3249 1021,塚本,3250 1022,播磨,3251 1023,高橋,3252 1024,周防,3253 1025,沢近,3254 1023,高橋,3252 1020,大森,3249 1023,高橋,3252 1024,周防,3253 実行結果: 1020:大森 1021:塚本 1022:播磨 1023:高橋 1024:周防 1025:沢近

ma_trix
質問者

補足

回答ありがとうございました。 書かれてあるとおりやってみると、 whileの文があると途中で処理が終わっちゃうみたいでHTMLが最後まで表示されない現象が起こりました。 で、こんな感じで組んでみたんですけど # while (@man) { # chomp; # push @table, $_; # } foreach (@man){ $H{$_}=1; } # @table = keys %H; foreach $eachman (sort keys %H) { ($num, $name, $encpass) = split(/,/, $eachman); 近いところまでいきました。 ただ、データが完全一致していないと重複チェックが消えないようで、1列目をキーにできればいいのですが、その方法はあるでしょうか? 実はデータは、 1020,大森,3249,5,8,0,,,,, みたいに後ろが続いてまして申し遅れましたm(__)m

すると、全ての回答が全文表示されます。

関連するQ&A