将多个值散列到perl中的一个键
Hashing multiple values to a key in perl
我正在读取一个单词文件,如果单词是变位词,则需要将它们散列为一个键。所以如果我读狗,我把这个词排序成 dgo。这将是我的钥匙。所以我读入了 god 这个词,它也会被排序为 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 创建一个新数组。然后我将原始单词推入数组。但如果密钥已经存在,我就会从哈希中获取数组并推送或添加下一个单词。
但这不能正常工作。我不能这样做吗?
是的,你可以做到这一点。但是你不能在散列中存储数组,你必须存储对它的引用。
push @{ $hash{$string} }, $original;
要检索数组,取消引用值:
print join ' ', @{ $hash{dgo} }; # dog god
你需要明白的是:perl 中没有二维数据结构这样的东西。你没有数组的散列,你有数组 references 的散列。
这可能会导致一些非常微妙的陷阱。
这例如 - 没有按照您的想法行事:
@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 'work with a reference' 的方式。 (在某些情况下你也可以使用 ->
符号。我省略了这个以避免混淆问题)
基本的 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
我正在读取一个单词文件,如果单词是变位词,则需要将它们散列为一个键。所以如果我读狗,我把这个词排序成 dgo。这将是我的钥匙。所以我读入了 god 这个词,它也会被排序为 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 创建一个新数组。然后我将原始单词推入数组。但如果密钥已经存在,我就会从哈希中获取数组并推送或添加下一个单词。
但这不能正常工作。我不能这样做吗?
是的,你可以做到这一点。但是你不能在散列中存储数组,你必须存储对它的引用。
push @{ $hash{$string} }, $original;
要检索数组,取消引用值:
print join ' ', @{ $hash{dgo} }; # dog god
你需要明白的是:perl 中没有二维数据结构这样的东西。你没有数组的散列,你有数组 references 的散列。
这可能会导致一些非常微妙的陷阱。
这例如 - 没有按照您的想法行事:
@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 'work with a reference' 的方式。 (在某些情况下你也可以使用 ->
符号。我省略了这个以避免混淆问题)
基本的 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