[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