Copying the first N keys and array hash values

I have a hash of arrays.

%HoA = ( 'C1' => ['1', '3', '3', '3'], 'C2' => ['3','2'], 'C3' => ['1','3','3','4','5','5'], 'C4' => ['3','3','4'], 'C5' => ['1'], ); 

I would like to write a subroutine that returns a hash of the โ€œsubcomponentโ€ of arrays that contains the first N keys (and their values) of the original hash of the arrays.

Something like that

 my %HoA2 = new_partition(\%HoA, 3); 

And it returns a new HoA data structure:

 %HoA = ( 'C1' => ['1', '3', '3', '3'], 'C2' => ['3','2'], 'C3' => ['1','3','3','4','5','5'], ); 

Is there a way to do this from scratch without using a module?

+4
source share
2 answers

There are no "first N elements" since the order of the hash keys is not defined and therefore cannot be relied upon.

If you need three elements instead of the first three, you can use

 %HoA = @HoA{ ( keys %HoA )[0..2] }; 
+3
source

As was correctly stated, the order of the elements in the hash is undefined. But if you can impose your own order on the elements, then simply extract the elements you need:

 my %HoA = ( 'C1' => ['1', '3', '3', '3'], 'C2' => ['3','2'], 'C3' => ['1','3','3','4','5','5'], 'C4' => ['3','3','4'], 'C5' => ['1'], ); # Use an array slice to grab the first 3 keys from a sorted list of %HoA keys. # Use map to create a new hash that contains the keys and the values from the # original hash: my %HoA2 = map { $_ => $HoA{$_} } (sort keys %HoA)[0..2]; # Alternatively, specify the exact keys that you require: my %HoA3 = map { $_ => $HoA{$_} } qw(C1 C2 C3); # { C1 => [1, 3, 3, 3], C2 => [3, 2], C3 => [1, 3, 3, 4, 5, 5] } 

Update

As Borodin points out, the above method copies the links, so changes to one hash will be reflected in another:

 push @{$HoA{C1}}, 9; # %HoA2 and %HoA3: # { C1 => [1, 3, 3, 3, 9], C2 => [3, 2], C3 => [1, 3, 3, 4, 5, 5] } 

To prevent this, copy the array itself:

 my %HoA4 = map { $_ => [@{ $HoA{$_} }] } qw(C1 C2 C3); 
+3
source

All Articles