Here's what I would do. It doesn't require constructing a (potentially) large array (which would only work if the weights are integers anyway), nor does it require two passes over the data (so the technique would also work when reading input from a stream).
The technique is discussed by Knuth.
my $pick;
my $weight;
while (my ($p, $w) = each %$group)
{
$weight += $w;
$pick = $p if rand ($weight) < $w;
}
#
# $pick now contains a weighted choice.
#