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