2012-04-16 8 views
4

私が頭を抱えることのできないコーディングの問題を助けてくれるかどうかは疑問でした。そう、Perl、データを重複した識別子と重複する値でマージしてハッシュにする方法

00001 AU:137 AU:150 AU:180 AU:170 
00002 AU:180 
00003 AU:147 AU:155 

だから、最初の列(識別子)が重複を削除、値をマージします:私はしたい出力がある

00001 AU:137 AU:150 AU:180 
00001 AU:137 AU:170 
00002 AU:180 
00003 AU:147 AU:155 
00003 AU:155 

:私はタブ区切りのデータは、以下のようなもののように見えますそれはハッシュになります。重複するキーを持つハッシュはできないので、現在のデータをどのように扱うかわかりません。また、識別子が同じであれば、データを配列にプッシュする方法もわかりません。

コードをお持ちでないことをお詫び申し上げます。私はいくつか、実際には、かなり多くを試みたが、彼らは自分のような初心者にも正しく見えない。

ご意見、ご協力をお待ちしております。ありがとうございます。私は大いに感謝します。

答えて

0

スクリプト:

#!/usr/bin/perl 

use strict; 
use warnings; 

my %hash; 
sub uniq { return keys %{{map {$_=>1} @_}}; } 

open my $fh, '<input.txt' or die $!; 
foreach (<$fh>) { 
    $hash{$1} .= $2 if /^(\S+)(\s.*?)[\n\r]*$/; 
} 
close $fh; 

foreach (sort keys %hash) { 
    my @elements = uniq split /\t/, $hash{$_}; 
    print "$_\t", join(' ', sort @elements), "\n"; 
} 

出力:

00001 AU:137 AU:150 AU:170 AU:180 
00002 AU:180 
00003 AU:147 AU:155 
+1

こんにちは。スクリプトをありがとう。残念ながら、私が望む結果を私に与えているわけではなく、各キーに重複した値を印刷しています。重複を取り除く方法はありますか?ありがとうございました。 – absolutenewbie

+0

@absolutenewbie - 私のスクリプトはコンピュータ上でうまく動作し、重複はありません。上のスクリプトを実行してもよろしいですか? –

+1

こんにちは。申し訳ありませんが、私はこれを明確にすべきです。出力例は同じです。私はなぜ私が持っているより大きいデータセットに私が重複を与えているのだろうと思っています...とにかく、ありがとうございました。あなたは、私が重複するキーを取り除くのに十分近いところに私を持ってきました今私は各キーの重複値を取り除く方法を見つける必要があります。再度、感謝します。 – absolutenewbie

3

私はこれがあなたの問題を解決するためにいくつかのアイデアを与える願っています:

use strict; 
use warnings; 
use Data::Dumper; 

my %hash =(); 

while (<DATA>) { 
    chomp; 
    my (@row) = split(/\s+/); 
    my $firstkey = shift @row; 

    foreach my $secondkey (@row) { 
      $hash{$firstkey}{$secondkey}++; 
    } 
} 

print Dumper \%hash; 

__DATA__ 
00001 AU:137 AU:150 AU:180 
00001 AU:137 AU:170 
00002 AU:180 
00003 AU:147 AU:155 
00003 AU:15 
+3

'my%hash =();'は冗長です。ちょうど 'my%hash;と言ってください。これは、偶然、あなたが 'my%hash = {}; 'を書くのを防ぎます。また、タブで区切られたデータの場合は、 '/ \ t /'(ブランクフィールドを無視したい場合は '/ \ t + /')に分割する必要があります。 – cjm

+1

'my%hash =()'はハッシュを再初期化し、 'my%hash'はスコープを定義するだけです。私は、複数の呼び出し(クロージャー)中にデータが利用可能であることを望まない場合は、常に変数をクリアする方が好きです。 'tab'については上書きされますので、' \ t'ははるかにクリーンです。 –

+1

'my' * always *は、以前の呼び出しに接続していない新しい空の変数を作成します。 – cjm

3

これに対する古典的な解決策はハッシュを使用します。実際にはハッシュのハッシュがあります。これは、行番号が重複し、行ごとに重複しているためです。

このプログラムは、必要な出力を生成します。これは、データファイルがコマンドラインで渡されることを期待しています。

use strict; 
use warnings; 

my %data; 

while (<>) { 
    chomp; 
    my ($key, @items) = split /\t/; 
    $data{$key}{$_}++ for @items; 
} 

print join("\t", $_, sort keys %{$data{$_}}), "\n" for sort keys %data; 

出力

00001 AU:137 AU:150 AU:170 AU:180 
00002 AU:180 
00003 AU:147 AU:155 

それとも、コマンド・ライン・ソリューション

perl -aF/\t/ -lne'$k=shift @F; $d{$k}{$_}++ for @F; END{print join "\t", $_, sort keys %{$d{$_}} for sort keys %d}' myfile 

を好む場合、私は唯一の存在で、Windows上でテストすることができますとして(それは少し調整が必要な場合があります。 )

関連する問題