Hash content extraction based on condition

↘锁芯ラ 提交于 2021-02-05 09:11:05

问题


I have a hash containing node data.

I am expecting hash content to be printed in -r_<count> and -d_<count> attributes.

Here is the script:

use strict; use warnings;

use Data::Dumper;

my %hash = (
    'Network=Test,Cell=31' => [ 'Network=Test,Unit=RU-1-1,Port=A',
                                'Network=Test,Unit=RU-1-2,Port=A'
                              ],
    'Network=Test,Cell=32' => [ 'Network=Test,Unit=RU-1-1,Port=A',
                                'Network=Test,Unit=RU-1-2,Port=A'
                              ],
    'Network=Test,Cell=33' => [ 'Network=Test,Unit=RU-1-5,Port=A',
                                'Network=Test,Unit=RU-1-6,Port=A'
                              ],
);

print "hash:\n".Dumper(\%hash);

my $count = 0;

foreach my $d (sort keys %hash) { 
    $count++;
    print "-d_". $count."=".$d . "\n";
    
    my %seen = ();
    foreach my $r (sort @{$hash{$d}}) {
        $seen{$r}++;
    }

    if ((keys %seen) > 0) {
        my $uniq = join ("###",sort keys %seen);
        print "-r_". $count . "=" . $uniq . "\n";
    } else {
        print "-r_". $count."="."NA\n";
    }
}

And I am able to print output like below(current output):

-d_1=Network=Test,Cell=31
-r_1=Network=Test,Unit=RU-1-1,Port=A###Network=Test,Unit=RU-1-2,Port=A
-d_2=Network=Test,Cell=32
-r_2=Network=Test,Unit=RU-1-1,Port=A###Network=Test,Unit=RU-1-2,Port=A
-d_3=Network=Test,Cell=33
-r_3=Network=Test,Unit=RU-1-5,Port=A###Network=Test,Unit=RU-1-6,Port=A

But I want output to be printed like below (expected output):

-r_1=Network=Test,Unit=RU-1-1,Port=A
-d_1=Network=Test,Cell=31###Network=Test,Cell=32
-r_2=Network=Test,Unit=RU-1-2,Port=A
-d_2=Network=Test,Cell=31###Network=Test,Cell=32
-r_3=Network=Test,Unit=RU-1-5,Port=A
-d_3=Network=Test,Cell=33
-r_4=Network=Test,Unit=RU-1-6,Port=A
-d_4=Network=Test,Cell=33

The expected output is, the value of -r_<count> should be printed as singular (from %hash keys array value) and -d_<count> (from %hash keys) should printed.


回答1:


The output is guided by the unique values of the arrays. Your output loop must therefore iterate over these.

(
   'Network=Test,Unit=RU-1-1,Port=A',
   'Network=Test,Unit=RU-1-2,Port=A',
   'Network=Test,Unit=RU-1-5,Port=A',
   'Network=Test,Unit=RU-1-6,Port=A',
)

However, for each of these, the output needs the associated keys. This means the output loop requires the following data:

(
   'Network=Test,Unit=RU-1-1,Port=A' => [ 'Network=Test,Cell=31', 'Network=Test,Cell=32' ],
   'Network=Test,Unit=RU-1-2,Port=A' => [ 'Network=Test,Cell=31', 'Network=Test,Cell=32' ],
   'Network=Test,Unit=RU-1-5,Port=A' => [ 'Network=Test,Cell=33' ],
   'Network=Test,Unit=RU-1-6,Port=A' => [ 'Network=Test,Cell=33' ],
)

Basically, your data structure is inside-out. But now that we know what we want, it's just a question of transforming the data structure into what we need.

my %foos_by_bar;
for my $foo (keys %hash) {   # %hash_b
   my $bars = $hash{$foo};   # %hash_a

   for my $bar (@$bars) {
      push @{ $foos_by_bar{$bar} }, $foo;
   }
}

The output loop simply needs to iterate over the (possibly sorted) keys of %foos_by_bar, and @{ $foos_by_bar{$bar} } contains the data you need for -d.


Nothing's stopping you from iterating over the sorted keys of %foos_by_bar in the output loop to produce predictable output, but that won't necessarily give you the same order as in the question. If you need that specific order, you can use the following:

my @bars;
my %foos_by_bar;
for my $foo (sort keys %hash) {   # %hash_b
   my $bars = $hash{$foo};        # %hash_a

   for my $bar (@$bars) {
      push @bars, $bar if !$foos_by_bar{$bar};
      push @{ $foos_by_bar{$bar} }, $foo;
   }
}

In this case, the output loop would iterate over @bars.



来源:https://stackoverflow.com/questions/64433535/hash-content-extraction-based-on-condition

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!