use Data::Dumper; my %hash = ( 'a'=>1, 'b'=>2, 'c'=>3, 'd'=>4, 'e'=>4, 'f'=>4); my %by_value = flip(%hash); print Data::Dumper->Dump([\%hash], ['*hash']); print Data::Dumper->Dump([\%by_value], ['*by_value']); sub flip { my($k, $v, %hash); my %foo = @_; $hash{$v} = defined $hash{$v} ? [ ref $hash{$v} ? @{$hash{$v}} : $hash{$v} , $k ] : $k while (($k,$v) = each %foo); return %hash; }