sarahJ
sarahJ

Reputation: 3

How to compare multiple values with each other for a key with in an hash in perl?

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

Answers (2)

Flying_whale
Flying_whale

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

Markus Ankenbrand
Markus Ankenbrand

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

Related Questions