我正在阅读一个单词文件,如果它们是字谜,则需要将单词哈希到一个键。因此,如果我读到狗,我会把这个词分成几个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创建一个新数组。然后我将原始单词推入数组。但是如果密钥已经存在,那么我从哈希中获取数组并推送或添加下一个单词。
但这并没有正常运作。我可以不这样做吗?
答案 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