可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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
回答1:
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
回答2:
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
回答3:
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