[Israel.pm] Case Study: Splitting a Hash into Two
Shlomi Fish
shlomif at iglu.org.il
Thu Jul 15 23:46:26 PDT 2004
On Wednesday 14 July 2004 22:43, Mikhael Goikhman wrote:
> On 14 Jul 2004 21:48:30 +0300, Shlomi Fish wrote:
> > Today I hanged around FreeNode's #perl channel. Someon asked for a way to
> > generate two hashes out of one, with one containing only the keys that
> > start with underscore, and the other the rest. After some thinking and
> > planning I came out with this code:
> >
> > <<<
> > sub split_hash
> > {
> > my $h = shift;
> > # us is underscore not the United States.
> > my (%us_hash, %non_us_hash);
> > while (my ($k, $v) = each(%$h))
> > {
> > (($k =~ /^_/o) ? \%us_hash : \%non_us_hash)->{$k} = $v;
> > }
> > return (\%us_hash, \%non_us_hash);
> > }
> >
> >
> > (tested, BTW).
>
> I think I would do it this way (at least if the run time is cheap):
>
> my %under_hash = map { $_ => $hash{$_} } grep /^_/, keys %hash;
> my %other_hash = map { $_ => $hash{$_} } grep !/^_/, keys %hash;
>
Yes, I thought about doing it this way as well. However, I decided against it,
because:
1. It iterates over the hash twice.
2. It has quite a lot of duplicate code.
3. If you have to split the hash into N groups, you'll have to iterate over it
N times.
#2 can be resolved, more or less by creating a small function. But my code,
with some variation can be made to work with the #3 provision:
sub split_hash
{
my $h = shift;
my $N = shift;
my $get_index = shift;
# Initializing so we'll always at least return an
# empty hash.
my @subsets = (map { +{} } (0)x$N);
while (my ($k, $v) = each(%$h))
{
$subsets[$get_index->($k,$v}]{$k} = $v;
}
return \@subsets;
}
(not tested)
Regards,
Shlomi Fish
> Regards,
> Mikhael.
--
---------------------------------------------------------------------
Shlomi Fish shlomif at iglu.org.il
Homepage: http://shlomif.il.eu.org/
Knuth is not God! It took him two days to build the Roman Empire.
More information about the Perl
mailing list