Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer

Slicing multilevel hashes

by bobf (Monsignor)
on Apr 07, 2005 at 17:14 UTC ( #445793=perlquestion: print w/replies, xml ) Need Help??
bobf has asked for the wisdom of the Perl Monks concerning the following question:

I'm trying to (ab)use hash slices. I understand the typical (@hash{@keys}) use of a slice, but now I'm trying to do something a bit more complex and take a slice of a hash of hashes. Using a slice in a %HoH when the list is provided as the second 'key' is no problem, but can slices be used to cut across the first set of keys as well? I didn't find anything when I searched for this in the docs or on PM.

Perhaps a bit of code will help define the problem:

use strict; use warnings; my @keys = qw( a c ); my %hash = ( a => 1, b => 2, c => 3, d => 4 ); # typical use - no problem # @hash{a,c} is like $hash{a}, $hash{c} print join( ' ', @hash{@keys} ), "\n"; # 1, 3 my %hoh = ( a => { a => 'a1', b => 'a2', c => 'a3', d => 'a4' }, b => { a => 'b1', b => 'b2', c => 'b3', d => 'b4' }, c => { a => 'c1', b => 'c2', c => 'c3', d => 'c4' }, d => { a => 'd1', b => 'd2', c => 'd3', d => 'd4' } ); # typical use expanded to a %HoH - no problem # @{ $hoh{b} }{a, c} is like $hoh{b}{a}, $hoh{b}{c} print join( ' ', @{ $hoh{b} }{@keys} ), "\n"; # b1, b3 # now I want to slice across the first key instead of the second # want something like $hoh{a}{d}, $hoh{c}{d} print join( ' ', @hoh{@keys}{d} ), "\n"; # syntax error # I tried dereferencing the list of hashrefs, but only # the last ref in the list was used ($hoh{c}) print join( ' ', @{ @hoh{@keys} }{d} ), "\n"; # c4 # do I have to resort to this? print join( ' ', map{ $_->{d} } @hoh{@keys} ), "\n"; # a4 c4

As illustrated in the code above, I used map to get it to work but if there is a way to use a slice I'd like to learn how to do it.

Aside: If this is possible, though, it immediately implies one could slice across both directions at once:

# yikes!! print join( ' ', @hoh{@keys}{@keys} ), "\n"; # a1 a3 c1 c3 ??


Update: clarified the main question

Replies are listed 'Best First'.
Re: Slicing multilevel hashes
by Roy Johnson (Monsignor) on Apr 07, 2005 at 17:33 UTC
    A slice -- even a hash slice -- is not a hash. It's a list (that includes only the values components, not the keys). That's why the sigil is @ and not %. You cannot hash-dereference a list. As dragonchild astutely suggested, you can use map to get the effect you want.
    map @{$_}{@keys}, @hoh{@keys};

    Caution: Contents may have been coded under pressure.

      Thanks for the speedy replies. I did use map to get a working solution (map{ $_->{d} } @hoh{@keys}) but I thought there might be another way to do it (thanks for the example). In the back of my mind I didn't think the @hoh{@keys}{d} idea was possible, but if it was then if anyone would know how to do it, it would be someone at Perl Monks!

Re: Slicing multilevel hashes
by dragonchild (Archbishop) on Apr 07, 2005 at 17:19 UTC
    You're trying to do a slice of a slice - not possible. Try slicing within a map across the outer slice.
Re: Slicing multilevel hashes
by bsb (Priest) on Apr 14, 2005 at 04:42 UTC

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://445793]
Approved by kvale
Front-paged by dmitri
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others surveying the Monastery: (8)
As of 2018-06-22 12:16 GMT
Find Nodes?
    Voting Booth?
    Should cpanminus be part of the standard Perl release?

    Results (124 votes). Check out past polls.