Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How would I use a hash slice to initialize a hash stored in a data structure?

In an earlier question I asked how to initialize a Perl hash using slices. It is done like this:

my %hash = ();
my @fields = ('currency_symbol', 'currency_name');
my @array = ('BRL','Real');
@hash{@fields} = @array;

Now let's imagine a more complex hash, and here is how it is initialized:

my %hash = ();
my $iso = 'BR';
$hash->{$iso}->{currency_symbol} = 'BRL';
$hash->{$iso}->{currency_name} = 'Real';
print Dumper($hash);

This results in the following:

$VAR1 = {
          'BR' => {
                    'currency_symbol' => 'BRL',
                    'currency_name' => 'Real'
                  }
        };

Now the question would be: how to initialize this particular hash using the splice method?

like image 786
emx Avatar asked Aug 24 '10 12:08

emx


3 Answers

The perllol documentation's Slices section covers array slices:

If you want to get at a slice (part of a row) in a multidimensional array, you're going to have to do some fancy subscripting. That's because while we have a nice synonym for single elements via the pointer arrow for dereferencing, no such convenience exists for slices. (Remember, of course, that you can always write a loop to do a slice operation.)

Here's how to do one operation using a loop. We'll assume an @AoA variable as before.

@part = ();
$x = 4;
for ($y = 7; $y < 13; $y++) {
  push @part, $AoA[$x][$y];
}

That same loop could be replaced with a slice operation:

@part = @{ $AoA[4] } [ 7..12 ];

Extrapolating to hash slices, we get

@{ $hash{$iso} }{@fields} = @array;

You know it's a hash slice because the “subscripts” are surrounded with curly braces rather than square brackets.

like image 132
Greg Bacon Avatar answered Oct 13 '22 09:10

Greg Bacon


First of all, since your hash is declared %hash, it would just be $hash{ $iso }. $hash->{ $iso } refers to a slot in the hash pointed to by $hash, which may or may not be pointing to %hash.

But once you have that, you can do the following:

@{ $hash{ $iso } }{ @fields } = qw<BRL Real>;

But as levels soon get complex, it's better to forgo the autovivification luxury and do the following:

my $h = $hash{ $iso }{blah}{blah} = {};
@$h{ @field_names } = @field_values;

Relocatable pointers within the hierarchy of hashes makes it easier to write anonymous accesses that also allow for easy slices.

like image 34
Axeman Avatar answered Oct 13 '22 11:10

Axeman


$hash{$iso} is going to be a hash reference. You replace what would be the variable name (without the sigil) in a simple slice with a block containing the reference, so:

@array{@list}

becomes

@{ $hash{$iso} }{@list}

See http://perlmonks.org/?node=References+quick+reference

like image 22
ysth Avatar answered Oct 13 '22 10:10

ysth