tags:

views:

1611

answers:

3

Lets say

%hash = (
        key1 => 'one',
        key2 => 'two',
        key3 => 'three',
        key4 => 'two',
        key5 => 'one',
);

I want to have two arrays:

  1. This array should have unique key/value

    @array1=(key1 one key2 two key3 three)

  2. this array should have count of duplicates by value (eg here only three value are unique so 'one' is found twice and 'two' found twice again and 'three' found once).

    @array2=(2 2 1)

+1  A: 

I'm not sure why you want the final answer to be in that strange form (as opposed to a hash of unique key/values and a hash of value=>count mappings, but here you go...

You can also use %counts hash directly instead of pushing values into an array as you wanted above.

use strict; 
use Data::Dumper;

my %hash = ( key1 => "one", key2 => "two", key3 => "three", key4 => "two", key5 => "one" );
my %counts = ();
my @counts = ();
my %unique = ();
foreach my $key (sort keys %hash) {
    my $value = $hash{$key}; 
    if (not exists $counts{$value}) {
        $unique{$key} = $value;
    }
    $counts{$value}++;
};
my @unique_keys = sort keys %unique; # Fix the sorting to your desired one 
                                     # if default is not what you meant

# You can also use %counts hash directly 
#instead of pushing values into an array as you wanted above.
foreach my $key (@unique_keys) {
    push @counts, $counts{ $unique{$key} }
};

# Print
print Data::Dumper->Dump([\@unique_keys, \@counts, \%unique],  
                         ["unique_keys", "counts", "unique"] ) ;

Results:

$unique_keys = [
                 'key1',
                 'key2',
                 'key3'
               ];
$counts = [
            2,
            2,
            1
          ];
$unique = {
            'key2' => 'two',
            'key1' => 'one',
            'key3' => 'three'
          };
DVK
I am quite new to perl .... yeah I agree with you that one can have hash with unique key/value as well. I actually wanted to have a record of all the values with their respective keys to be counted. I just didnt know how to do that using hash .... thanx a lot ..... i got what I wanted .....
Suren
+2  A: 

Ignoring the order issue ...

#!/usr/bin/perl

use strict;
use warnings;

my %hash = qw( key1 one key2 two key3 three key4 two key5 one );

my %counts;
$counts{ $_ }++ for values %hash;

my %uniq = reverse %hash;

my (@array1, @array2);

while ( my ($k, $v) = each %uniq ) {
    push @array1, $v, $k;
    push @array2, $counts{$k};
}

use Data::Dumper;
print Dumper \@array1, \@array2;


__END__

C:\Temp> t.pl
$VAR1 = [
          'key3',
          'three',
          'key5',
          'one',
          'key2',
          'two'
        ];
$VAR2 = [
          1,
          2,
          2
        ];
Sinan Ünür
yeah. Even this one works perfectly with my problem. thank you.thanx to all of you. This was my first post and never expected such a quick response and different ways of doing the same thing.
Suren
A: 

my %hash = ( key1 => 'one', key2 => 'two', key3 => 'three', key4 => 'two', key5 => 'one', );

my %counts;

$counts{$_}++ foreach values %hash;

my @elements = keys %hashes;

my @frequency = values %hashes;