Reputation: 173
my %hash1 = (
a=>192.168.0.1,
b=>192.168.0.1,
c=>192.168.2.2,
d=>192.168.2.3,
e=>192.168.3.4,
f=>192.168.3.4
);
i have a perl hash like given above. keys are device names and values are ip addresses.How do i create a hash with no duplicate ip addresses (like %hash2) using %hash1? (devices that have same ips are removed)
my %hash2 = ( c=>192.168.2.2, d=>192.168.2.3 );
Upvotes: 3
Views: 1923
Reputation: 486
A solution using the CPAN module List::Pairwise:
use strict;
use warnings;
use List::Pairwise qw( grep_pairwise );
use Data::Dumper;
my %hash1 = (
a => '192.168.0.1',
b => '192.168.0.1',
c => '192.168.2.2',
d => '192.168.2.3',
e => '192.168.3.4',
f => '192.168.3.4'
);
my %count;
for my $ip ( values %hash1 ) { $count{ $ip }++ }
my %hash2 = grep_pairwise { $count{ $b } == 1 ? ( $a => $b ) : () } %hash1;
print Dumper \%hash2;
It's pretty straightforward. First you count the IPs in an auxiliary hash. And then you select only those IPs with a count of one using grep_pairwise
from List::Pairwise
. The syntax of grep_pairwise
is like grep
:
my @result = grep_pairwise { ... } @list;
The idea of grep_pairwise
is to select the elements of @list
two by two, with $a
representing the first element of the pair, and $b
the second (in this case the IP). (Remember that a hash evaluates to a list of ($key1, $value1, $key2, $value2, ...) pairs in list context).
Upvotes: 1
Reputation: 2501
First of all you need to quote your IP addresses, because 192.168.0.1
is V-String in perl, means chr(192).chr(168).chr(0).chr(1)
.
And my variant is:
my %t;
$t{$_}++ for values %hash1; #count values
my @keys = grep
{ $t{ $hash1{ $_ } } == 1 }
keys %hash1; #find keys for slice
my %hash2;
@hash2{ @keys } = @hash1{ @keys }; #hash slice
Upvotes: 6
Reputation: 91385
How about:
my %hash1 = (
a=>'192.168.0.1',
b=>'192.168.0.1',
c=>'192.168.2.2',
d=>'192.168.2.3',
e=>'192.168.3.4',
f=>'192.168.3.4',
);
my (%seen, %out);
while( my ($k,$v) = each %hash1) {
if ($seen{$v}) {
delete $out{$seen{$v}};
} else {
$seen{$v} = $k;
$out{$k} = $v;
}
}
say Dumper\%out;
output:
$VAR1 = {
'c' => '192.168.2.2',
'd' => '192.168.2.3'
};
Upvotes: 3