问题
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