开发者

How do I find and count duplicate values in a perl hash

I need to find the duplicate values in a perl hash and then output the key/value pair and associated dup count whe开发者_开发知识库n that count is > 1.

(I could leave a code sample of what I've attempted but that would just result in mass confusion and possibly uncontrolled laughter, and I'm really hoping to make it through life with some semblance of self esteem.)

Hash key/value would look like the following:

%hash = qw('FHDJ-124H' => 'hostname1', 'HJDHUR-87878' => 'hostname2', 'HGHDJH-874673' => 'hostname1');

My desired output would be:

2 duplicates found for hostname1
    FHDJ-124H
    HGHDJH-874673

Using perl 5.6 on Solaris 10. Tightly controlled production environment where upgrading or loading perl mods is not allowed. (A change request for moving to 5.8 is about 6 months out).

Many thanks!


You need to iterate through the hash keys in your first hash (key/value) and accumulate the count of each item you find in another hash (value/count).

If you want to display the keys together with duplicated values, your second hash cannot be as simple as that, since for each duplicated value you will have a collection of keys (all of them having the same value). In this case, simply accumulate the key in an array, then count its elements. I.e., your second hash would be something like (value/[key1,key2,key3...])

my %hash = ( key1 => "one", key2 => "two", key3 => "one", key4 => "two", key5 => "one" );
my %counts = ();
foreach my $key (sort keys %hash) {
    my $value = $hash{$key}; 
    if (not exists $counts{$value}) {
        $counts{$value} = [];
    }
    push $counts{$value}, $key;
};

Then iterate over $counts to output what you need when the count of elements in $counts{$value} > 1


This is what you are looking for

#!/usr/bin/perl
use strict;
use warnings;
my %hash = ('FHDJ-124H' => 'hostname1', 'HJDHUR-87878' => 'hostname2', 'HGHDJH-874673' => 'hostname1');
my %reverse;

while (my ($key, $value) = each %hash) {
    push @{$reverse{$value}}, $key;
}

while (my ($key, $value) = each %reverse) {
    next unless @$value > 1;

    print scalar(@$value), " duplicates found \n @$value have the same key $key\n";     

}


What about:

#!/usr/bin/perl
use strict;
use warnings;
use Data::Dump qw(dump);

my %h = (a=>'v1', b=>'v2', c=>'v1', d=>'v3', e=>'v3');
my %r;
while(my($k,$v)=each%h){
    push @{$r{$v}}, {$k=>$v};
}
dump %r;

output:

(
  "v1",
  [{ c => "v1" }, { a => "v1" }],
  "v2",
  [{ b => "v2" }],
  "v3",
  [{ e => "v3" }, { d => "v3" }],
)


Well, off of the top of my head, you could do something like this:

my @values=sort(values(%hash));
my @doubles=();
my %counts=();



foreach my $i (0..$#values)
{
    foreach my $j (($i+1)..$#values)
    {
        if($values[$i] eq $values[$j])
        {
            push @doubles,$values[$i];
            $counts{$values[$i]}++;

        }
    }
}

foreach(@doubles)
{
    print "$hash{$_}, $_, $counts{$_}\n";
}

This is a bit of a naive solution (that I haven't tested, yet), and I'm sure there's a faster and slicker way, but this should work.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜