gpt4 book ai didi

perl - 从散列键列表中反序列化嵌套散列

转载 作者:行者123 更新时间:2023-12-03 21:35:26 24 4
gpt4 key购买 nike

我有一个想要“unflatten”或“tree-ify”的字符串;也就是说,我想从这个开始:

F=8|A_C=3|A_B=2|D_G_H=11|D_B=2|E=5  

对此:
{
A => {
B => 2,
C => 3,
},
D => {
B => 2,
G => {
H => 11,
},
},
E => 5,
F => 8,
}

我的策略是分别处理每个以竖线分隔的字段并由 = 分割。登录键/值对:
sub unflatten {
my ($data) = @_;
my @fields = split /\|/, $data;
my $result = {};

for my $datum (@fields) {
my ($key, $value) = split /=/, $datum;
$result->{&processline($key)} = $value;
}
return $result;
}

我在 processline 中尝试了一些递归魔法。功能:
sub processline {
my ($key) = @_;

my ($first, $rest) = split /_/, $key, 2; # split key into at most 2 parts
if($rest) {
return { $first => &processline($rest) };
# if the key is nested, there will be something in $rest
# so recursively process the smaller $rest, and build up the result hashref
}
else {
return $first;
}
}

不幸的是,这不起作用:
my $header = "F=8|A_C=3|A_B=2|D_G_H=11|D_B=2|E=5";
use Data::Dumper;
print Dumper &unflatten($header);

当我这样做时,我得到:
$VAR1 = {
'F' => '8',
'HASH(0xe9af60)' => '2',
'HASH(0xe9ae28)' => '11',
'E' => '5',
'HASH(0xe9af90)' => '3',
'HASH(0xe9ae40)' => '2'
};

有人可以解释递归解决方案背后的思考过程,或者建议我的 Perl 哪里出了问题?令人沮丧的是,我能够很容易地想出这个函数的反函数(展平)。

最佳答案

我相信使用简单的 for 会更直接。循环比使用递归。您选择的方法无法工作,因为它只使用 processline 返回的单个键。分配值,并且不能创建多级哈希。

递归解决方案的工作方式是获取哈希引用、键列表和值,并定义

unflatten($hash, 'key1_key2_key3_key4', 'value')

作为
unflatten($hash->{key1}, 'key2_key3_key4', 'value')`

这个程序演示了一个简单的循环解决方案。它使用指针 $hash它从结果哈希的根开始,并在列表中的每个键之后向前移动一个级别。
sub unflatten {

my $result = {};

for my $item (split /\|/, $_[0]) {

my ($keys, $value) = split /=/, $item;
my @keys = split /_/, $keys;
my $hash = $result;

while (@keys > 1) {
my $key = shift @keys;
$hash->{$key} ||= {};
$hash = $hash->{$key};
}

$hash->{$keys[0]} = $value;
}

return $result;
}

输出
$VAR1 = {
'A' => {
'C' => '3',
'B' => '2'
},
'F' => '8',
'D' => {
'G' => {
'H' => '11'
},
'B' => '2'
},
'E' => '5'
};

更新

现在我回到了键盘,这是一个递归解决方案。它会产生与原始哈希相同的哈希
use strict;
use warnings;

use Data::Dumper;

my $data = 'F=8|A_C=3|A_B=2|D_G_H=11|D_B=2|E=5';

my $result = {};
unflatten2($result, $_) for split /\|/, $data;
print Dumper $result;

sub unflatten2 {
my ($hash, $data) = @_;

if ($data =~ /_/) {
my ($key, $rest) = split /_/, $data;
unflatten2($hash->{$key} ||= {}, $rest);
}
else {
my ($key, $val) = split /=/, $data;
$hash->{key} = $val;
}
}

更新

您可能还对 Data::Diver 感兴趣模块,它适用于这样的情况,虽然文档有点笨拙

这是使用它的解决方案的外观
use strict;
use warnings;

use Data::Diver qw/ DiveVal /;
use Data::Dumper;

my $data = 'F=8|A_C=3|A_B=2|D_G_H=11|D_B=2|E=5';

my $result = {};

for (split /\|/, $data) {
my ($keys, $val) = split /=/;
DiveVal($result, split /_/, $keys) = $val;
}

print Dumper $result;

关于perl - 从散列键列表中反序列化嵌套散列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24093567/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com