我是Perl的新手,我正在尝试以递归方式构建哈希并且无处可去。我尝试搜索动态构建哈希的教程,但我能找到的只是关于哈希的介绍性文章。如果你指出我正确的方向或建议一篇好文章/教程,我将不胜感激。
我正在尝试从具有
形式的路径的文件中读取one/two/three
four
five/six/seven/eight
我想构建像
这样的哈希VAR = {
one : {
two : {
three : ""
}
}
four : ""
five : {
six : {
seven : {
eight : ""
}
}
}
}
我目前使用的脚本是:
my $finalhash = {};
my @input = <>;
sub constructHash {
my ($hashrf, $line) = @_;
@elements = split(/\//, $line);
if(@elements > 1) {
$hashrf->{shift @elements} = constructHash($hashrf->{$elements[0]}, @elements );
} else {
$hashrf->{shift @elements} = "";
}
return $hashrf;
}
foreach $lines (@input) {
$finalhash = constructHash($finalhash, $lines);
}
答案 0 :(得分:7)
Data::Diver
很好地涵盖了这个利基,人们不应该重新发明轮子。
use strict;
use warnings;
use Data::Diver 'DiveVal';
use Data::Dumper;
my $root = {};
while ( my $line = <DATA> ) {
chomp($line);
DiveVal( $root, split m!/!, $line ) = '';
}
print Dumper $root;
__DATA__
one/two/three
four
five/six/seven/eight
答案 1 :(得分:6)
这有点牵强,但它确实有效:
sub insert {
my ($ref, $head, @tail) = @_;
if ( @tail ) { insert( \%{$ref->{$head}}, @tail ) }
else { $ref->{$head} = '' }
}
my %hash;
chomp and insert \%hash, split( '/', $_ ) while <>;
它依赖于自动更新,对于初学者而言,这无疑是有点先进的。
你的问题的任何答案可能会有点扭曲,你要求叶子中的空字符串,它与节点的哈希值有不同的“类型”,并且需要不同的解除引用操作。
答案 2 :(得分:4)
我从来没有做过这样的事情,所以这种做法可能是错的,但好吧,这是我的镜头:
use 5.013;
use warnings;
use Data::Dumper;
sub construct {
my $hash = shift;
return unless @_;
return construct($hash->{shift()} //= {}, @_);
}
my %hash;
while (<DATA>) {
chomp;
construct(\%hash, split m!/!);
}
say Dumper \%hash;
__DATA__
one/two/three
four
five/six/seven/eight
编辑:已修复!
EDIT2:A(我认为)尾部调用优化版本,因为!
sub construct {
my $hash = shift;
return unless @_;
unshift @_, $hash->{shift()} //= @_ ? {} : '';
goto &construct;
}
答案 3 :(得分:3)
我运行了你的代码并发现了一些问题:
@elements
。constructHash()
是一个字符串,但是在内部的递归调用中,你传递了一个@elements
试试这个。
use Data::Dumper;
my $finalhash = {};
my @input = split "\n", <<INPUT;
one/two/three
four
five/six/seven/eight
INPUT
sub constructHash {
my $line = shift;
my ($first, $remainder) = split(/\//, $line,2);
if ($remainder) {
return { $first => constructHash($remainder) } ;
} else {
return { $first , "" };
}
}
foreach $lines (@input) {
my $linehash = constructHash($lines);
my $firstkey = (keys %$linehash)[0];
# print Dumper $linehash;
$finalhash->{$firstkey} = $linehash->{$firstkey};
}
print Dumper $finalhash;
它产生
$VAR1 = {
'five' => {
'six' => {
'seven' => {
'eight' => ''
}
}
},
'one' => {
'two' => {
'three' => ''
}
},
'four' => ''
};
请记住,Perl哈希值不是有序的。
答案 4 :(得分:1)