Perl: многоизмерен хеш

да предположим, че имам следните данни

клъстер1:d(A),f(C)s,(A)

клъстер2:r(D),h(D),f(A)

Искам това да излезе

изход:

   cluster1:A->2
   cluster1:C->1
   cluster2:D->2
   cluster2:A->1

ето моя опит, но не е правилен, частта, която се опитвам да преброя знаците, има проблем, че не мога да поправя кода, е част от много голям код и искам точно многоизмерен хеш

use strict;
use Data::Dumper;
 my %count;
while (<DATA>) {
    my %HoH;
    my ( $cluster, $ch ) = split (/:/,$_);
    $HoH{$cluster}={split /[()]+/,$ch}; 
    for my $clust ( keys %HoH ) {
        for my $character ( keys %{ $HoH{$clust} } ) {
            $count{$clust}{$HoH{$clust}{$character}}++;
     }
    }
}
print Dumper(\%count);
foreach my $name (sort keys %count) {
    foreach my $subject (keys %{$count{$name}}) {
        print "$name:$subject->$count{$name}{$subject}\n";
    }
}

ДАННИ

клъстер1:d(A),f(C)s,(A)

клъстер2:r(D),h(D),f(A)


person shaq    schedule 13.09.2012    source източник
comment
Форматът на въвеждане също е много различен сега.   -  person flesk    schedule 13.09.2012
comment
@flesk: да, трябваше да напиша всичко от самото начало, сега този код работи с малък бъг   -  person shaq    schedule 13.09.2012


Отговори (2)


Би било хубаво, ако се опитате да разберете кода по-долу, за да можете да получите представа за решаването на проблема: -

    use strict;
    use Data::Dumper;

    my $data = "cluster1:A,B,C,A";
    my %cluster = ();

    my ($cluster_key, $cluster_val ) = split (':', $data);
    my @cluster1_data = split(',', $cluster_val);


    foreach my $val ( @cluster1_data ) {
    $cluster{$cluster_key}{$val}++;
    }
    print Dumper(\%cluster);


    foreach my $clus ( keys %cluster ) {
    my $clus_ref = $cluster{$clus};
        foreach my $clu ( keys %{ $clus_ref } ){
          my $count = $clus_ref->{$clu};
          print"$clus:$clu->$count\n";
        }
    }

Изход:

$VAR1 = {
          'cluster1' => {
                          'A' => 2,
                          'C' => 1,
                          'B' => 1
                        }
        };


cluster1:A->2
cluster1:C->1
cluster1:B->1
person Nikhil Jain    schedule 13.09.2012
comment
Редактирах въпроса си, а също и кода си, моля, вижте какъв е проблемът - person shaq; 13.09.2012

Какво точно очаквате да направи $count{$cluster}{$characters}+=1;? Трябва да преминете през вашите входни данни, за да попълните %count, ако очаквате да получите желания резултат:

while (<DATA>) {
    next unless /^(cluster\d+):(.+)/;
    $count{$1}{$_}++ for split/,/, $2;
}

Ако добавите също sort към второто foreach, ще получите резултата, който искате.

РЕДАКТИРАНЕ: Това решава въпроса за актуализирания вход и изисквания:

my %count;

while (<DATA>) {
    next unless /^(cluster\d+):(.+)/;
    my $cluster = $1;
    $count{$cluster}{$_}++ for $2 =~ /\((\w)\)/g;
}

for my $key (sort keys %count) {
    for my $value (sort {
        $count{$key}{$b} <=> $count{$key}{$a}
                   } keys %{$count{$key}}) {
        print "$key:$value->$count{$key}{$value}\n";
    }
}
person flesk    schedule 13.09.2012
comment
@shaq: вижте perldoc.perl.org/perldata.html#Special-Literals ако сте объркани от нещото <DATA>. - person simbabque; 13.09.2012
comment
не, не съм объркан от данните, но се чудя дали можете да актуализирате кода, да предположим, че имам клъстера в $cluster и символи в $character след това какво трябва да напиша - person shaq; 13.09.2012
comment
@simbabque: Добра гледна точка. Освен това, ако четете данните си от файлов манипулатор, заменете DATA с името на файловия манипулатор. О, и току-що забелязах, че знаците не са сортирани, така че не съм сигурен каква е логиката зад подреждането? - person flesk; 13.09.2012
comment
@shaq: Можете да напишете $count{$cluster}{$_}++ for split/,/, $characters;, за да постигнете това. - person flesk; 13.09.2012