如何组合散列哈希,而不是预先?

时间:2012-07-09 19:39:33

标签: perl perl-data-structures perl-hash

我想在Perl中的哈希中创建哈希结构,但所有教程(如章节9.4。哈希哈希哈希Programming Perl中)都预先添加它们。我想最初创建结构,然后在读取文件时使用子程序填充空哈希。

例如,我想阅读一本书,并且每个页面都会跟踪单词以及它们在页面中出现的行。

以下结构:

%Parent = (
    1 => {
        "the" => [1, 4],
        "and" => [2, 3]
    },
    2 => {
        "but" => [1, 2],
        "as"  => [3, 4]
    }
)

表示单词the出现在第1页的第1行和第4行,but出现在第2页的第1行和第2行,等等。

我该怎么做?我试图这样做的每一种方式我似乎都无法坚持我的哈希并且正在失去他们的价值观等。

3 个答案:

答案 0 :(得分:4)

"the" => (1, 4), "and" => (2, 3)

是一种奇怪的写作方式

"the", 1, 4, "and", 2, 3

,如果分配给哈希,将等同于

%h = ();
$h{"the"} = 1;
$h{4} = "and";
$h{2} = 3;

你想要

%Parent = (
    1 => {
        "the" => [ 1, 4 ],
        "and" => [ 2, 3 ]
    },
    2 => {
        "but" => [ 1, 2 ],
        "as"  => [ 3, 4 ]
    }
)

就像{ }创建一个哈希,将内部表达式的结果(如果有的话)分配给哈希,并返回对该哈希的引用,[ ]创建一个数组,分配结果数组的内部表达式(如果有的话),并返回对该数组的引用。


当然,没有一个能回答你的问题!关于你的问题。

my %Parent = (
    1 => {
        "the" => [1, 4],
        "and" => [2, 3]
    },
    2 => {
        "but" => [1, 2],
        "as"  => [3, 4]
    }
);

基本等同于

my %Parent;
$Parent{1}{the}[0] = 1;
$Parent{1}{the}[1] = 4;
$Parent{1}{and}[0] = 2;
$Parent{1}{and}[1] = 3;
$Parent{2}{but}[0] = 1;
$Parent{2}{but}[1] = 2;
$Parent{2}{as }[0] = 3;
$Parent{2}{as }[1] = 4;

push通常比分配填充数组更方便。那看起来像是:

my %Parent;
push @{ $Parent{1}{the} }, 1;
push @{ $Parent{1}{the} }, 4;
push @{ $Parent{1}{and} }, 2;
push @{ $Parent{1}{and} }, 3;
push @{ $Parent{2}{but} }, 1;
push @{ $Parent{2}{but} }, 2;
push @{ $Parent{2}{as } }, 3;
push @{ $Parent{2}{as } }, 4;

感谢autovivification,

push @{ $Parent{$k1}{$k2} }, $n;

的缩写
push @{ ( $Parent{$k1} //= {} )->{$k2} //= [] }, $n;

答案 1 :(得分:3)

错误在于将列表表达式分配给二级哈希中的单词键。这必须是一个arrayref,例如"the" => [1, 4]

# assume $page, $line defined
for my $word (@words) {
    push @{ $Parent{$page}{$word} }, $line;
}

答案 2 :(得分:0)

在开始时将$ Parent初始化为var:

my $Parent; # we will use this to store ref of parsed hash 

假设您在$ page中存储页码,在$ word中存储单词并在$ line中存储行 在您想要存储新行号时解析文件时,您可以使用以下代码:

if(exists $Parent->{$page} and $Parent->{$page}->{$word}){
  push( @{ $Parent->{$page}->{$word} },$line);
}else{
  $Parent->{$page}->{$word} = [$line];
}

我们确保如果$ Parent-> {$ page} - > {$ word}尚未初始化,请先使用匿名数组初始化它。如果它存在,那么只需将行号推入其中。