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.
精彩评论