ダブりを消す方法は?

このQ&Aのポイント
  • データの中でダブっている行を消す方法について教えてください。
  • 現在、データの中でダブっている行を消すために特定の処理を行っているのですが、うまくいっていません。効果的な方法を教えてください。
  • ダブっている行を除去するために使用しているコードが思うように動作していません。改善策を教えてください。
回答を見る
  • ベストアンサー

ダブりを消す

データの中でダブっている行を消したいのですがどうしたらよいでしょうか? 例えば $a,$b,$c,$d,$e,$f,$g,$h 1,2,3,4,5,6,7,8 1,2,3,4,5,6,7,8 1,1,1,1,1,1,1,1 と三行あって一行目と二行目がダブっているので一つにしたいのです↓。 1,2,3,4,5,6,7,8 1,1,1,1,1,1,1,1 いま作っているのは while ($record = <FILE>) { chomp $record; push @array,$record; @x = sort keys %{{map {$_,1} @array}}; } close FILE; foreach (@x){ print OUT "$_\n"; } としてやっていますがなかなかうまくいきません。 良い方法があれば教えてください

  • Perl
  • 回答数3
  • ありがとう数5

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

  • ベストアンサー
  • bonyamk
  • ベストアンサー率29% (49/166)
回答No.3

$TMP{$record} = $record; これは仮想配列です {}のなかがキーになっていますので 同じ行(キー)があった場合に上書きされてダブりがなくなるってことです 仮想配列についてはperlの本に必ずついていて便利なものなので覚えておくといいですよ^^ while ($record = <FILE>) { chomp $record; $TMP{$record} = $record; } close FILE; foreach (keys(%TMP)){ print "$_\n"; } こんな感じで取り出します

bunsho11
質問者

お礼

本当に丁寧にありがとうございます。

その他の回答 (2)

  • bonyamk
  • ベストアンサー率29% (49/166)
回答No.2

#1です 間違えました^^; while ($record = <FILE>) { chomp $record; $TMP{$record} = $record; }

bunsho11
質問者

お礼

どうもありがとうございます。 こんなに早くできるとは思いませんでした。 あと恐縮ですが $TMP{$record} = $record; の意味を教えていただければうれしいです。

  • bonyamk
  • ベストアンサー率29% (49/166)
回答No.1

while ($record = <FILE>) { chomp $record; $TMP{$_} = $_; } だめかな?^^;

関連するQ&A

  • ファイル内で重複している数と重複した回数

    開くファイルの中身は数字のみ。 1行に一つずつ数字が入っており、 それが何行にもわたり続くファイルです。 ファイル内で重複している数と重複した回数を数えたいです。 以下のようなスクリプトを使ったのですが、 結果を表示させようとすると global symbol"$hash" requires explicit package name. にエラーが出ます。 何故なのでしょうか。 use strict; # ファイルを開く my $INPUT_FILE; open ($INPUT_FILE, ">numbers.dat") or die “Can't open. \n”; # それぞれの数をハッシュキーにする。そして対応するバリューを同じ数を見つける度毎にカウントアップする。 my %hash = (); while (my $line = readline($INPUT_FILE)) { chomp $line; $hash{$line}++; } # キーでソートし、結果を表示する。 my @keys = sort keys %hash; foreach my $key (@keys) { print “$key is found $hash{$key} times\n”; } close ($INPUT_FILE) or die “can't close the file\n”;

    • ベストアンサー
    • Perl
  • whileの$_とforeachの$_の関係

    以下のコードにおけるwhileとforeachでの$_の使いかたについて教えてください。 my @foos = qw( a b ); sub foo1 {   open FH, "foo.txt";   while (<FH>) {     chomp;     print "$_";   } #  while (my $x = <FH>) { #    chomp $x; #    print "$x"; #  }      print "\n"; } sub foo2 {   foreach (@foos) {     print "<$_>";     foo1();   }   print "\n"; } foo2(); foo2(); このコードと同じディレクトリに以下のような内容のfoo.txtをおいて実行します。 x y すると、以下のような結果が得られました。 <a>xy <b>xy <>xy <>xy 一回目のfoo2で@foosの内容が消えてしまいます。一方、コメントアウトしてあるようにwhileに変数($x)を使うと期待したとおりの結果が出ます。なぜ、このような結果になるのでしょうか。ご存知の方がいらっしゃったら教えてください。宜しくお願いします。ちなみに、WinXP + ActivePerl(v5.8.6)で試しました。

    • ベストアンサー
    • Perl
  • ランダム文字列

    srand; @array = a .. z; @new; while ( @array ) { push( @new, splice(@array , rand @array , 1) ); } print @new, "\n\n"; print "<br>"; print @new, "\n\n"; print "<br>"; print @new, "\n\n"; ↑のような感じでランダム文字列の作成を考えています。 上記スクリプトですと、 aewpodigtusnkjycfxvmzqrlhb aewpodigtusnkjycfxvmzqrlhb aewpodigtusnkjycfxvmzqrlhb ↑のようにどの行も同一文字列になってしまいます。これを、行毎に異なった8文字のランダム文字列にしたいのですが、方法がわかりません。 いっぺんに100行のランダム文字列を生成する必要があります。どうぞよろしくお願いいたします。

    • ベストアンサー
    • Perl
  • 静的ハッシュの配列のキーに対応する値の数の多さ順で表示させたい

    ハッシュのキーに対応する値の数の多さ順で表示させたいと考え、下記の所まで試行錯誤しておりますが、どうにも思ったようにソートできずにおります。 #!/usr/bin/perl use strict; my(%a, $i, $j ,$allarray ,@keys ,@keys2 ,%hash ,%files ,$a_mumei_ref ,$key ,$value ,@value ,$x ,$files); # ハッシュの配列を静的に作る %a = ( '0' => [ qw(0) ], '1' => [ qw(1 1) ], '3' => [ qw(3 3 3) ], '7' => [ qw(7 7 7) ], '2' => [ qw(2) ], '4' => [ qw() ], '5' => [ qw() ], '6' => [ qw() ], '8' => [ qw(8 8) ], '9' => [ qw(9) ], ); @keys = sort { $hash{$b} <=> $hash{$a} || length($b) <=> length($a) || $a cmp $b } keys %a; #ハッシュのキーを数字順で表示 foreach (@keys){ print $_ ."\n"; } # 静的に作ったハッシュの配列を取り出してみる foreach $i (sort keys %a) { for ($j = 0; $j <= scalar(@{$a{$i}})-1; $j++) { print '$a{'. $i. '}['. $j. ']='. $a{$i}[$j]. ' '; } $allarray=scalar(@{$a{$i}})-1; print "No$i:kosuu:$allarray"; print "\n"; #配列の値の個数を調べその配列を作成 my($a_mumei) = $allarray; $a_mumei_ref = \$a_mumei; $files{"$i"}=($i,$a_mumei_ref); } #each関数で%filesの中身を表示 while ( ( $key , $value ) = each %files ){ print "key:$key value:$$value\n" ; } #試行錯誤 foreach $x (sort { $files{$b} <=> $files{$a} } keys %files){ print "$x => $files->{$x}\n"; } @keys2 = sort {$hash{$a} <=> $hash{$b}} keys %files; #@keys2 = sort { $hash{$b} <=> $hash{$a} || length($b) <=> length($a) || $a cmp $b } keys %files; #@keys2 = sort { $hash{$a} cmp $hash{$b} } keys %files; print "@keys2\n"; print "\n"; __END__; 私のイメージしておりますのは、ソートした結果がハッシュのキーに対応する値の数の多さ順で下記のように表示させたいのですが、 どのようにすれば可能でございますか、ご教授願えませんでしょうか key:3 value:2・・・この場合valueは配列の個数 key:7 value:2 key:8 value:1 key:1 value:1 key:9 value:0 key:2 value:0 key:0 value:0 key:6 value:-1 key:4 value:-1 key:5 value:-1

    • ベストアンサー
    • Perl
  • プリントすると 保存位置が表示される

    %classをプリントしたいのですが、 保存位置が表示されるだけで肝心の中身が出てきません。 どうしたら 表示できますか? 前略 push @{$class{$name}->{grade}}, @grade とやって保存し、以下で表示させようとしました。 foreach my $key (sort keys(%class)) { print "$key:"; my @values = %{input{$key}}; print join',', @values; print ".\n"; }

  • 先頭の単語が一致した時のデータ追加

    【データ】 (A) A A2 "one" 7 A 3C three 9 B DD "two" 11 C CDE four 25 C 4D five 33 D YY six 27 ・ ・ (B) A okinawa kagoshima miyazaki B kumamoto oita D fukuoka E saga nagasaki ・ (A)と(B)のデータを比較し、先頭の単語が一致した時のみ、先頭の単語を除いた(B)の行を (A)の末尾に加えるという処理をしたいです。 【目標】 A A2 "one" 7 okinawa kagoshima miyazaki A 3C three 9 okinawa kagoshima miyazaki B DD "two" 11 kumamoto oita C CDE four 25 C 4D five 33 D YY six 27 fukuoka ・ ・ 以前、回答して頂いた方法を踏まえ、以下の処理を行いましたが上記のような結果がでません。 宜しくお願いします。 #!/usr/bin/perl open(FILE1, "<aaa.txt") || die "File1 Open Error! \n"; open(FILE2, "<bbb.txt") || die "File2 Open Error! \n"; open(OUT, ">zzz.txt") || die "OUT Open Error! \n"; my @data1 = <FILE1>; my @data2 = <FILE2>; chomp @data1; chomp @data2; foreach my $line1 (@data1) { my @array1 = split(/\t/, $line1); push @{$hash1{$array1[0]}}, @array1[1, -1]; for my $key1 (sort keys %hash1){ foreach my $line2 (@data2) { my @array2 = split(/\t/, $line2); push @{$hash2{$array2[0]}}, @array2[1, -1]; for my $key2 (sort keys %hash2){ if($key1 eq $key2){ print OUT join("\t", ($key2, @{$hash2{$key2}}, @{$hash1{$key1}})), "\n"; } } } } }

    • ベストアンサー
    • Perl
  • ソート時同じ値がある場合、表示順をコントロールする事は可能ですか?

    ハッシュの配列を配列の数の多い順に表示する場合で配列の数が同じの場合の最初に表示される配列の数字につきまして この配列の数が同じである場合の表示順序を意図した順番にする事は可能でございますか? この意図した順番と申しますのは、小さい数字を先に表示するのではなく下記の@array2の配列値の並んでいる順や別途配列に0~9の数字を適当に入れておきにそれを参考に評価するという形を希望しており模索中なのですが、まずこの事につきまして可能か不可能かをご教授願いたいのと、もし可能でしたらどうか解決に至る先輩方のお知恵をお借り出来ませんでしょうか よろしくお願い致します。 #!/usr/bin/perl use Tie::IxHash; @array0_n=('a','b','c','d'); @array1_n=('e','f','g'); @array2_n=('h','i'); @array3_n=('j'); @array4_n=(); @array5_n=(); @array6_n=('k'); @array7_n=('l','n'); @array8_n=('m','o','p'); @array9_n=('q','r','s','t'); %array1 = ( '0' => [ (@array0_n) ], '1' => [ (@array1_n) ], '2' => [ (@array2_n) ], '3' => [ (@array3_n) ], '4' => [ (@array4_n) ], '5' => [ (@array5_n) ], '6' => [ (@array6_n) ], '7' => [ (@array7_n) ], '8' => [ (@array8_n) ], '9' => [ (@array9_n) ], ); #配列の数の多い順に並び替え my @array2 =reverse sort { scalar @{$array1{$b}} <=> scalar @{$array1{$a}} or $a <=> $b } keys %array1; @array9_n2=('a2','b2','c2','d2'); @array1_n2=('e2','f2','g2'); @array2_n2=('h2','i2'); @array3_n2=('j2'); @array4_n2=(); @array5_n2=(); @array6_n2=('k2'); @array7_n2=('l2','n2'); @array8_n2=('m2','o2','p2'); @array0_n2=('q2','r2','s2','t2'); tie %TmpList, 'Tie::IxHash'; #@array2を元に更に動的にハッシュ内に配列を作成 foreach(@array2){ my $x="array$_\_n2"; $TmpList{$_}=[(@$x)]; print "$_,$#{$x},@$x<br>\n"; } print "1-end\n"; while ( ( $key , $value ) = each %TmpList ){ print "key:$key value:@$value\n" ; } print "2-end\n"; my @array3 = sort { scalar @{$TmpList{$b}} <=> scalar @{$TmpList{$a}} or $a <=> $b } keys %TmpList; #Tie::IxHashモジュールで表示する際の順番を固定出来るかテスト foreach(@array3){ my $x="array$_\_n2"; $TmpList2{$_}=[(@$x)]; print "$_,$#{$x},@$x<br>\n"; } print "3-end\n"; __END__;

    • ベストアンサー
    • Perl
  • 1ファイルずつ読み込みたい

    ウィンドウズ環境でactive perlを利用しています。 あるディレクトリーの中に2000位のファイルが入っており、このファイルを読み込んで置換処理を行うため下記のようなperlを作っています。 1ファイルはおおよそ3000行くらいです。 foreach(<*.html>) { open(IN_FILE, $_) || die; open(OUT, ">$_.tmp") || die; @record=<IN_FILE>; foreach $record (@record){ $record =~s/aaa/bbb/isg; } print OUT @record; close( IN_FILE); close( OUT); rename("$_.tmp", $_) ; } 当たり前かもわかりませんが、メモリー不足になり処理が中断します。 ディレクトリーの中のファイル数を600程度に少なくすると処理が完了します。 そこで質問なのですが、ディレクトリーの中のファィルを一度に全部読み込まず、1ファイルずつ順次読み込んでいくことはできないでしょうか。 最初の1行目のforeachをwhileに変えたりしたのですがうまくいきません。 対応策あればご教示ください。

    • ベストアンサー
    • Perl
  • ファイルの入出力と改行

    縦100文字横70文字のデータが入ったデータファイルを横50文字にして並べ直したいと思い、まず試しに標準出力でそれがうまくいくかやってみたのですが、うまくいきません。もしお分かりであれば教えていください。よろしくお願いいたします。 #! /usr/bin/perl $filename = "reference.txt"; open HANDLE, "<$filename" or die "cannot open :$!"; print "open success\n"; @array = <HANDLE>; $count = 1; foreach $var (@array) { chomp $var; # print $var; if($count==50){ print $var, "\n"; } else{ print $var; } $count++; } close HANDLE; print "\n";

    • ベストアンサー
    • Perl
  • 検索後の「見つかりません」がたくさんでてしまいます。

    こんにちは!初歩的な質問失礼致します。 HTMLで名前を検索して、見つけると名前・出身地・その他を表示するというプログラミングを作っています。 検索にひっかかるときちんと表示されるとこまでいったのですが、検索で引っかからなければ「見つからない」と表示させようとして、elseをつかうと「見つからない」がたくさん出てきてしまい困っています。 サブルーチン・番兵君を使えば良いと書いてありますがはっきしどう使えばいいかわかりません。 下記がプログラムの一部なのですが open(rd,"./file.txt"); @file = <rd>; close(rd); foreach $ww2 (@file){ ($name,$shushin,$other) = split(/,/,$ww2); chomp($name); chomp($shushin); chomp($other); $SHU{$name} = $shushin; $OTHER{$name} = $other; } @name1 = keys ( %SHU ); foreach $string (@name1){ #chomp($string); #print "$string と$FORM{'item1'}<br>"; if($string eq $FORM{'item1'}){ print "見つかった名前:$string <br>     出身地:$SHU{$string} <br>     その他:$OTHER{$string}\n"; } } 「見つからない!」を一回だけ表示させるにはどうしれば良いでしょうか? 申し訳ないですが上記にプログラムを追加して、解説の方宜しくお願い致します。

    • ベストアンサー
    • Perl

専門家に質問してみよう