Perl 嵌套哈希匹配和合并
Perl nested hashes matching and merging
我有一个文件被读取并拆分为 %objects,%objects 填充如下所示。
$VAR1 = 'cars';
$VAR2 = {
'car1' => {
'info1' => '"fast"',
'info2' => 'boring'
},
'car2' => {
'info1' => '"slow"',
'info2' => 'boring info'
},
'car3' => {
'info1' => '"unique"',
'info2' => 'useless info'
}
};
$VAR3 = 'age';
$VAR4 = {
'new' => {
'info3' => 'rust',
'info4' => '"car1"'
},
'old' => {
'info3' => 'shiny',
'info4' => '"car2" "car3"'
}
}
};
我的目标是在数据库中插入诸如“car1 fast rust, car2 slow shiny, car3 unique shiny”之类的数据,但我无法获得,例如“根据年龄信息 4 进行匹配”..
my $key = cars;
my $key2 = age;
foreach my $obj (keys %{$objects{$key}}) { # for every car
@info1s = $objects{$type}{$obj}{'info1'} =~ m/"(.*?)"/g; # added to clean up all info1
foreach my $infos ($info1s) {
dbh execute insert $obj $infos # this gives me "car1 fast, car2 slow, car3 unique"
}
...
有人可以指出正确的方向来获取和存储 info4 以及相关的 info1/info2 吗?
谢谢!
我取objective如下。
在最深层次的 hashref 中获取 $VAR4
中 (info4
) 键的值,并在 $VAR2
hashref 中找到它们作为顶级键。然后将它们与来自 (info3
) 键的值、它们自己 $VAR4
最深层次 hashref 中的“兄弟”以及键值 (info1
) 来自 $VAR2
.
可以为此目的手动遍历结构,特别是如果它始终具有如图所示的相同两个级别,但使用库更容易和更好。我使用 Data::Leaf::Walker to get leaves (deepest values) and key-paths to them, and Data::Diver 获取已知路径的值。
use warnings;
use strict;
use feature 'say';
use Data::Dump;
use Data::Leaf::Walker;
use Data::Diver qw(Dive);
my $hr1 = {
'car1' => { 'info1' => 'fast', 'info2' => 'boring' },
'car2' => { 'info1' => 'slow', 'info2' => 'boring info' },
'car3' => { 'info1' => 'unique', 'info2' => 'useless info' }
};
my $hr2 = {
'new' => { 'info3' => 'rust', 'info4' => 'car1' },
'old' => { 'info3' => 'shiny', 'info4' => 'car2 car3' }
};
my $walker = Data::Leaf::Walker->new($hr2);
my %res;
while ( my ($path, $value) = $walker->each ) {
next if $path->[-1] ne 'info4';
# Some "values" have multiple needed values separated by space
for my $val (split ' ', $value) {
# Get from 'info4' path the one to its sibling, 'info3'
my @sibling_path = ( @{$path}[0..$#$path-1], 'info3' );
# Collect results: values of `info3` and `info1`
push @{$res{$val}},
Dive( $hr2, @sibling_path ),
Dive( $hr1, ($val, 'info1') );
}
}
dd \%res;
为简单起见,这假设了一些事情并采取了一些捷径。
首先,我使用问题中的显式 infoN
键和两级结构。如果数据不同,或者可能不同,这应该不难调整。
接下来,假设像 car1
这样的值始终作为另一个 hashref 中的键存在。添加一个 exists
检查该键,如果它可能不作为键存在。
我从数据中删除了一些额外的引号。 (如果这是用于数据库条目,请在构造语句时执行此操作。如果数据带有此类额外引号,则调整代码以将其考虑在内应该很容易。)
以上程序打印
{
car1 => ["rust", "fast"],
car2 => ["shiny", "slow"],
car3 => ["shiny", "unique"],
}
(我使用 Data::Dump 来显示复杂的数据结构,因为它的简单性和默认的紧凑输出。)
我有一个文件被读取并拆分为 %objects,%objects 填充如下所示。
$VAR1 = 'cars';
$VAR2 = {
'car1' => {
'info1' => '"fast"',
'info2' => 'boring'
},
'car2' => {
'info1' => '"slow"',
'info2' => 'boring info'
},
'car3' => {
'info1' => '"unique"',
'info2' => 'useless info'
}
};
$VAR3 = 'age';
$VAR4 = {
'new' => {
'info3' => 'rust',
'info4' => '"car1"'
},
'old' => {
'info3' => 'shiny',
'info4' => '"car2" "car3"'
}
}
};
我的目标是在数据库中插入诸如“car1 fast rust, car2 slow shiny, car3 unique shiny”之类的数据,但我无法获得,例如“根据年龄信息 4 进行匹配”..
my $key = cars;
my $key2 = age;
foreach my $obj (keys %{$objects{$key}}) { # for every car
@info1s = $objects{$type}{$obj}{'info1'} =~ m/"(.*?)"/g; # added to clean up all info1
foreach my $infos ($info1s) {
dbh execute insert $obj $infos # this gives me "car1 fast, car2 slow, car3 unique"
}
...
有人可以指出正确的方向来获取和存储 info4 以及相关的 info1/info2 吗?
谢谢!
我取objective如下。
在最深层次的 hashref 中获取 $VAR4
中 (info4
) 键的值,并在 $VAR2
hashref 中找到它们作为顶级键。然后将它们与来自 (info3
) 键的值、它们自己 $VAR4
最深层次 hashref 中的“兄弟”以及键值 (info1
) 来自 $VAR2
.
可以为此目的手动遍历结构,特别是如果它始终具有如图所示的相同两个级别,但使用库更容易和更好。我使用 Data::Leaf::Walker to get leaves (deepest values) and key-paths to them, and Data::Diver 获取已知路径的值。
use warnings;
use strict;
use feature 'say';
use Data::Dump;
use Data::Leaf::Walker;
use Data::Diver qw(Dive);
my $hr1 = {
'car1' => { 'info1' => 'fast', 'info2' => 'boring' },
'car2' => { 'info1' => 'slow', 'info2' => 'boring info' },
'car3' => { 'info1' => 'unique', 'info2' => 'useless info' }
};
my $hr2 = {
'new' => { 'info3' => 'rust', 'info4' => 'car1' },
'old' => { 'info3' => 'shiny', 'info4' => 'car2 car3' }
};
my $walker = Data::Leaf::Walker->new($hr2);
my %res;
while ( my ($path, $value) = $walker->each ) {
next if $path->[-1] ne 'info4';
# Some "values" have multiple needed values separated by space
for my $val (split ' ', $value) {
# Get from 'info4' path the one to its sibling, 'info3'
my @sibling_path = ( @{$path}[0..$#$path-1], 'info3' );
# Collect results: values of `info3` and `info1`
push @{$res{$val}},
Dive( $hr2, @sibling_path ),
Dive( $hr1, ($val, 'info1') );
}
}
dd \%res;
为简单起见,这假设了一些事情并采取了一些捷径。
首先,我使用问题中的显式 infoN
键和两级结构。如果数据不同,或者可能不同,这应该不难调整。
接下来,假设像 car1
这样的值始终作为另一个 hashref 中的键存在。添加一个 exists
检查该键,如果它可能不作为键存在。
我从数据中删除了一些额外的引号。 (如果这是用于数据库条目,请在构造语句时执行此操作。如果数据带有此类额外引号,则调整代码以将其考虑在内应该很容易。)
以上程序打印
{ car1 => ["rust", "fast"], car2 => ["shiny", "slow"], car3 => ["shiny", "unique"], }
(我使用 Data::Dump 来显示复杂的数据结构,因为它的简单性和默认的紧凑输出。)