如果我有像下面的阵列,其中,所述元素的顺序是随机的,也有在每个元件可以多少层没有限制。 这里只显示3个级别。 a
, b
,和c
。
我希望能够解析这样的阵列,并且将结果存储在哈希像这样的哈希,当只有3个级别
$VAR1 = {
'a' => {
'b' => 'c'
}
};
题
我的问题是如何写这个正则表达式,因为第一级不具有/
末,并且因为元素的顺序是随机的,如果a/b/c
已经在哈希插入,然后元素a
不应该为删除键的哈希值a
。
所以如何解决这样的问题?
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
my @ar = ("a", "a/b", "a/b/c");
my %h = ();
foreach my $a (@ar) {
}
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
use Data::Diver 'DiveRef';
my @array = ("a", "a/b", "a/b/c");
my %hash = ();
foreach my $element (@array) {
DiveRef( \%hash, \( split /\//, $element ) );
}
通常你会分配给或修改DiveRef返回的标量引用(或指定DiveVal的结果),但在这里你只是想确保键存在。
在\(...)
变为由分返回到标引用的列表,它告诉数据::潜水员这些总是会被哈希键,不可能数组索引,如果他们是数字列表。
要得到
"a" => $tree = "a";
"a", "a/b" => $tree = { "a" => "b" };
"a", "a/b", "a/b/c" => $tree = { "a" => { "b" => "c" } };
"a", "a/b", "a/c" => $tree = { "a" => { "b" => undef, "c" => undef } };
码:
my $tree;
for ("a", "a/b", "a/b/c") {
my @keys = split qr{/};
my $val = pop(@keys);
my $p = \$tree;
while (@keys) {
my $key = shift(@keys);
$$p = { $$p => undef } if !ref($$p);
$p = \( ($$p)->{$key} );
}
if (defined($$p)) {
$$p = { $$p => undef } if !ref($$p);
($$p)->{$val} = undef;
} else {
$$p = $val;
}
}
但是,这不是一个很好的数据结构,因为你需要使用ref
浏览它。 相反,我建议
"a" => $tree = { "a" => undef };
"a", "a/b" => $tree = { "a" => { "b" => undef } };
"a", "a/b", "a/b/c" => $tree = { "a" => { "b" => { "c" => undef } } };
"a", "a/b", "a/c" => $tree = { "a" => { "b" => undef, "c" => undef } };
码:
my $tree;
for ("a", "a/b", "a/b/c") {
my $p = \$tree;
$p = \( ($$p)->{$_} ) for split qr{/};
}
看到它是多么简单建立这个数据结构? 当您尝试浏览它,你会得到类似的好处。
请注意,您可以使用数据::潜水员创建第二个数据结构(虽然我记得它是慢得多)。
use Data::Diver qw( DiveRef );
my $tree;
for ("a", "a/b", "a/b/c") {
DiveRef($tree //= {}, \split(qr{/}));
}
一个例子:
my @ar = ("a", "a/b", "a/b/c");
my %h;
for (@ar) {
my $levels = split /\//;
for (my $i = 0; $i <= $#levels; $i++) {
# How ever you want to set-up your hash of hashes
# But each for loop iteration would give you a "level" of input
}
}