Reputation: 3
I have an hash which looks something like this
my %hash = (key1 => [value1],
key2 => [value1,value2],
key3 => [value3,value3,value3],
key4 => [value2,value2,value2]
);
Now I want to compare these values with one other and pick out the odd key.i.e., the key for which all values are not same and in this case it's key2
Taking out each key and iterating over arrays seem to be ordeal.Is there an easy way to do that?
I want to use this odd key and print out values/give it a count in an hash
for ex.
my %hash2;
$hash2{key2}{value1} =2;
$hash2{key2}{value2} =2;
How do I accomplish this?
Upvotes: 0
Views: 527
Reputation: 377
use warnings;
use strict;
my @odd_keys;
my %hash = (key1 => [1],
key2 => [1,2],
key3 => [3,3,3],
key4 => [2,2,2]
);
foreach my $key (keys(%hash))
{
#builds an array with every cell equal to first cell
my @temp_array = grep {$_ eq $hash{$key}->[0]} @{$hash{$key}};
#if the size of this array is different than the size of array associated to key, that means that all values are not equal
if (@temp_array != @{$hash{$key}})
{
print "$key\n";
push(@odd_keys, $key);
}
}
prints odd keys and creates an @odd_keys array
Upvotes: 1
Reputation: 523
In order to find your key of interest you can filter for those values that have more than one unique element. For uniq
you can either use List::MoreUtils
or if you want to avoid modules you can define the function yourself (explanation here)
sub uniq {
my %seen;
return grep { !$seen{$_}++ } @_;
}
You can then filter the keys like this:
# get an array of pairs of "uniq count" and "key"
my @key_counts = map {[uniq(@{$hash{$_}})+0, $_]} keys %hash;
# filter this array for those with "uniq count" greater than 1 and only keep key
my @keys_of_interest = map {$_->[1]} grep {$_->[0] > 1} @key_counts;
# if you know that there is only a single key of interest
my $key = $keys_of_interest[0];
You can use this $key
and the corresponding value
to get your %hash2
:
my %hash2;
$hash2{$key}{$_} = 2 foreach(@{$hash{$key}});
Upvotes: 2