将多个值散列到perl中的键

时间:2015-03-20 16:28:08

标签: arrays perl hash hashmap key-value

我正在阅读一个单词文件,如果它们是字谜,则需要将单词哈希到一个键。因此,如果我读到狗,我会把这个词分成几个dgo。这将是我的关键。所以我在上帝这个词中读到,它也将被分类为dgo,它们应该都是哈希到同一个键。

这是我正在尝试但我不确定我是否正确地这样做。

    if(exists $hash{$string})
    {
            @values2 = $hash{$string};
            push @values2, $original; 

            for my $word (@values2)
            {
                print $word."\n";
            }
            #print "Hello";
    } 

    else
    {
         @values = ();
        $hash {$string} = @values;  
        push @values, $string; 
    }   
}

所以$string是我的排序单词,关键。因此,如果密钥不存在,我会在该密钥上为我的$ hash创建一个新数组。然后我将原始单词推入数组。但是如果密钥已经存在,那么我从哈希中获取数组并推送或添加下一个单词。

但这并没有正常运作。我可以不这样做吗?

3 个答案:

答案 0 :(得分:1)

你需要理解的是:perl中没有二维数据结构这样的东西。你没有数组哈希,你有一个数组引用的哈希

这可能导致一些非常微妙的陷阱。

这就是 - 例如 - 没有按照你的想法行事:

@values = ();
$hash{$string} = @values;
push @values, $string;

它正在清空@values。但是它在标量上下文中分配它。这意味着你要设置:

$hash{$string} = 0; 

然后将$string插入@values,但是这样就会使哈希值与没有不同,因为您已将哈希值设置为空数组的大小。

同样如此:

@values2 = $hash{$string};
push @values2, $original;

for my $word (@values2) {
    print $word. "\n";
}

你只是永远最多会检索一个数组引用(但是如果你已经填充了else块,它甚至都没有那 - 它只是0)这意味着你的for循环不起作用。 $hash{$key}只能是单个值。

如果要哈希键设置为数组;

 $hash{$string} = [@values]; 

如果您想添加元素:

 push ( @{$hash{$string}}, @values ); 

如果你想提取元素;

my @array = @{ $hash{$string} }; 

你需要额外的印记,因为这就是你如何告诉perl使用参考文献'。 (在某些情况下,您也可以使用->表示法。我省略了这一点以避免混淆问题)

答案 1 :(得分:0)

是的,你可以这样做。但是你不能将数组存储在哈希中,你必须存储对它的引用。

push @{ $hash{$string} }, $original;

要检索数组,请解除值:

print join ' ', @{ $hash{dgo} }; # dog god

答案 2 :(得分:0)

基本Perl数据结构是关于单个值的。变量$foo只能存储单个值。数组@foo可以存储单个值的数组。哈希%foo有一个指向值的键。

如果您需要更多(例如指向多个值的键),您需要了解Perl References。 Perl引用是Perl数据结构(例如散列或数组),其中每个条目不是指向单个值,而是指向另一个结构。

在您的情况下,您希望您的密钥(单词dgo)指向包含这些字母的单词的数组

想象一下这样的事情:

my @dgo_words = qw(dog dgo god gdo odg ogd);   # All possible combinations
$words{dgo} = \@dgo_words;   # The '\' means this is a reference to @dgo_words

现在,words{dgo}指向数组@dgo_words引用。如果取消引用引用(通过在变量上添加正确的前缀),我可以返回到数组:

my @array_of_dgo_words = @{ $words{dgo} };

请记住,$words{dgo}指向数组,将@放在前面可以访问该数组。在这种特殊情况下,花括号是可选的:

my @array_of_dgo_words = @$words{dgo};

就个人而言,我更喜欢大括号,因为它突出了这是一个参考。其他人认为消除它们会使代码更容易阅读。

如果@{ $words{dgo} }是我的数组,我可以使用push向数组中添加字词:

push @{ $words{dgo} }, 'dog';

现在,dog被添加到$words{dgo}引用的数组中。

这是一个简单的程序:

#! /usr/bin/env perl

use strict;
use warnings;
use feature qw(say);


my %words;
#
# First add all the words into the correct key
#
while ( my $word = <DATA> ) {
    chomp $word;
    my $key = join '', sort split //, $word;
    push @{ $words{$key} }, $word;
}

for my $group ( sort keys %words ) {        # For each key in my word hash
    my @word_group = @{ $words{$group} };   # Dereference to get the list of words
    say qq(Words for group "'$group":);
    for my $word ( @word_group ) {          # This loop prints out the words
        say "    $word";
    }
}

__DATA__
dog
bog
save
god
gob
vase