Reputation: 29116
I have a set of data that I would like to process.
In order to simplify my code, It would be nice to access to some subsets of my data through array of references that point to the original data.
Better than an explanation, I wrote down this example (which is not working yet). At the end, I would like to update the original data without having to also update all the subsets.
Is it possible to do something like this with Perl ?
#!/usr/bin/env perl
use strict;
use warnings;
# A set of data
my $design = {
box => {
ne => {data => 'north-east'},
nw => {data => 'north-west'},
n => {data => 'north'},
s => {data => 'south'},
e => {data => 'east'},
w => {data => 'west'},
se => {data => 'south-east'},
sw => {data => 'south-west'}
}
};
# Select a design
my $selected = 'box';
# Build some arrays
my $d = $design->{$selected};
my @eastside = (\$d->{e}, \$d->{ne}, \$d->{se});
my @westside = (\$d->{w}, \$d->{nw}, \$d->{sw});
my @northside = (\$d->{n}, \$d->{ne}, \$d->{nw});
# Update one data
$d->{ne}->{data} .= " updated!";
# Display
print join '', "Composed of:\n", map("\t".$_->{data}."\n", @eastside);
The script should output:
Composed of:
east
north-east updated!
south-east
Upvotes: 4
Views: 116
Reputation: 63952
You can check the data structure with Data::Dumper module.
Also check the next two @east2
and @east3
examples, especially how is built the @east3
.
#!/usr/bin/env perl
use 5.010;
use warnings;
use Data::Dumper;
# A set of data
my $design = {
box => {
ne => {data => 'north-east'}, nw => {data => 'north-west'},
n => {data => 'north'}, s => {data => 'south'},
e => {data => 'east'}, w => {data => 'west'},
se => {data => 'south-east'}, sw => {data => 'south-west'}
}
};
my $selected = 'box';
my $d = $design->{$selected};
#your example
my @east1 = (\$d->{e}, \$d->{ne}, \$d->{se});
say Dumper \@east1;
my @east2 = ($d->{e}, $d->{ne}, $d->{se});
say Dumper \@east2;
my @east3 = @$d{qw(e ne se)};
say Dumper \@east3;
$d->{ne}->{data} .= " updated!";
print join '', "Composed of:\n", map("\t".$$_->{data}."\n", @east1);
print join '', "Composed of:\n", map("\t".$_->{data}."\n", @east2);
print join '', "Composed of:\n", map("\t".$_->{data}."\n", @east3);
prints:
$VAR1 = [
\{
'data' => 'east'
},
\{
'data' => 'north-east'
},
\{
'data' => 'south-east'
}
];
$VAR1 = [
{
'data' => 'east'
},
{
'data' => 'north-east'
},
{
'data' => 'south-east'
}
];
$VAR1 = [
{
'data' => 'east'
},
{
'data' => 'north-east'
},
{
'data' => 'south-east'
}
];
Composed of:
east
north-east updated!
south-east
Composed of:
east
north-east updated!
south-east
Composed of:
east
north-east updated!
south-east
Upvotes: 2
Reputation: 126742
All that is wrong is that you are taking a reference of values that are already hash references in the lines like
my @eastside = (\$d->{e}, \$d->{ne}, \$d->{se})
You should simple omit the backslashes and everything will work.
(By the way, you may want to know that the reference \
operator is distributive, so you can write the same thing with
my @eastside = \( $d->{e}, $d->{ne}, $d->{se} )
but it's no more correct that way!)
Some other points
You should make use of hash slices in situations like this where you need to extract a list of hash elements using multiple keys. In this case @eastside
is just @{$d}{qw/ ne e se /}
Perl allows the indirection operator ->
between pairs of closing and opening braces and brackets to be omitted, so $d->{ne}->{data}
can be written $d->{ne}{data}
You are printing the result of a join
with a null between the elements. You'll get the same result by just listing the items to be printed. You can also interpolate hash elements into a double-quoted string, so "\t".$_->{data}."\n"
is the same as "\t$_->{data}\n"
Making those changes results in this working program
use strict;
use warnings;
# A set of data
my $design = {
box => {
ne => {data => 'north-east'},
nw => {data => 'north-west'},
n => {data => 'north'},
s => {data => 'south'},
e => {data => 'east'},
w => {data => 'west'},
se => {data => 'south-east'},
sw => {data => 'south-west'},
}
};
# Select a design
my $selected = 'box';
# Build some arrays
my $d = $design->{$selected};
my @eastside = @{$d}{qw/ ne e se /};
my @westside = @{$d}{qw/ nw w sw /};
my @northside = @{$d}{qw/ nw n ne /};
# Update one item
$d->{ne}{data} .= " updated!";
# Display
print "Composed of:\n";
print " $_->{data}\n" for @eastside;
output
Composed of:
north-east updated!
east
south-east
Upvotes: 2
Reputation: 50657
You have scalar references in @eastside
array, so in order to dereference scalar put extra $
in front of $_->{data}
, or use ${$_}->{data}
.
print join '', "Composed of:\n", map("\t".$$_->{data}."\n", @eastside);
output
Composed of:
east
north-east updated!
south-east
Upvotes: 2