Suren
Suren

Reputation: 173

removing duplicate hash value and keeping a count of it in perl

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)

Upvotes: 1

Views: 11372

Answers (3)

Ankur
Ankur

Reputation:

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;

Upvotes: 0

Sinan Ünür
Sinan Ünür

Reputation: 118166

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
        ];

Upvotes: 2

DVK
DVK

Reputation: 129539

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'
          };

Upvotes: 1

Related Questions