一个哈希表是否可以有重复的键或值?

11
哈希表可以有重复的值,但是键必须是唯一的。

1
哦,没想到哈希是 Perl 中关联数组的名称(有点奇怪)。 - Jake T.
1
@Jake T.,Perl的关联数组是哈希表。 - ikegami
1
@Jake T => 我写了一个关于名称“哈希”的评论,它是“哈希表”的缩写,这是一种使用哈希函数实现的数据结构,用于将任意字符串映射到桶数组的索引,每个桶包含一个短链表的键值对,使用字符串比较与请求的键进行比较。如果链接列表变得足够长,则扩展桶数组,更新字符串和索引之间的相应映射,并重新排序数据。最优解决方案将努力最小化此效果的影响。 - Eric Strom
来自perl.com:Perl对术语“哈希”(hash)的使用可能会引起一些混淆,因为哈希函数的输出有时也被称为哈希(尤其是在加密上下文中),而哈希表通常在其他地方不被称为哈希。为了保险起见,请将数据结构称为哈希表,并仅在明显的Perl特定上下文中使用术语“哈希”。 - Jake T.
1
@Jake T.,那又怎样?由于加密哈希既没有键也没有值,在OP的请求中不会产生混淆。此外,上下文是特定于Perl的。 - ikegami
显示剩余7条评论
6个回答

17

它可以有重复的值,但不能有重复的键。


11

对于哈希和数组,每个键(key)只能存储一个标量(scalar)。("键(key)是唯一的")。如果不是这样,你将无法进行

$h{a} = 1;
$h{a} = 2;
$val = $h{a};  # 2

$a[4] = 1;
$a[4] = 2;
$val = $a[4];  # 2
如果你想将多个值与一个键关联起来,你可以在该键上放置对数组(或哈希)的引用,并将值添加到该数组(或哈希)中。
for my $n (4,5,6,10) {
    if ($n % 2) {
        push @{ $nums{odd} }, $n;
    } else {
        push @{ $nums{even} }, $n;
    }
}

say join ', ', @{ $nums{even} };

更多内容请参见perllol

至于值,在哈希和数组中,多个元素可以具有相同的值。

$counts{a} = 3;
$counts{b} = 3;

$counts[5] = 3;
$counts[6] = 3;

6

假设我们谈论的是“%hash”。

那么:

  • 不允许重复键。
  • 允许重复值。

这很容易理解,因为它将一个特定的键映射到一个特定的值,其中该值在查找中不起作用,因此独立于其他值。


3
请尝试运行此代码,它可以无错误执行。 希望这就是您想要的!
#!/usr/bin/perl

use strict;
use warnings;

my %hash = ('a' => 1, 'a' => 2, 'b' => 4 );

print values %hash, "\n\n";
print keys %hash, "\n\n";

2
您可以尝试使用来自CPAN的Hash::MultiKey模块。
(我使用Data :: Dumper显示哈希表的确切外观-这里不是必要的)
use Data::Dumper;
use Hash::MultiKey;

tie my %multi_hash, 'Hash::MultiKey';

$multi_hash{['foo', 'foo', 'baz']} = "some_data";

for (keys %multi_hash) {
    print @$_,"\n";
};

print Dumper\%multi_hash;

输出应该是():
foofoobaz
$VAR1 = {
          'ARRAY(0x98b6978)' => 'some_data'
        };

从技术上讲,Hash::MultiKey 允许您创建引用作为哈希键。

-1

是的,哈希表可以有重复的键,就像我下面演示的那样...

键的例子:出生日期|姓氏前四个字符|名字首字母|编号 "1959-12-19|Will|K|1" ... "1959-12-19|Will|K|74"。
注意:如果有人忘记了他们的社会安全号码,这可能是一个有用的记录查找键。

   #-- CODE SNIPPET:
   @Offsets=();     #-- we will build an array of Flat File record "byte offsets" to random access
                    #-- for all records matching this ALT KEY with DUPS       
   for ($i=1; $i<=99; $i++) {
       $KEY=$BirthDate . "|" . $LastNameFirst4Chars . "|" . $FirstNameInitial . "|" . $i; 
       if (exists $Hash{$KEY}) {
           push @Offsets, $Hash{$KEY};  #-- add another hash VALUE to the end of the array
       }
   } 

1
这说明了什么?在您的代码运行后,@Offsets%Hash都没有改变(即仍为空)。该代码只是为变量$KEY生成99个不同的值,例如blabla|1blabla|2,... blabla|99 - PerlDuck
好的,但是在Perl中的标准哈希表绝对不可能有重复的键。你例子中的键都是不同的。"$BirthDate|...|1""$BirthDate|...|2"是不同的,对吧?所以这些键并不是重复的。 - PerlDuck
PerlDuck,序列号使键唯一。如果我有一个唯一主键,比如社会保障号码。当我想要访问数据库中的记录时,但是我不记得SSN,那么我可以使用带有重复项的ALT KEY,例如:“$BirthDate|$LastNameFirst4Chars|$FirstNameInitial|SeqNbr”。 “1959-12-19|Will|K|1…“1959-12-19|Will|K|99”。键中的所有数据都是重复的,除了序列号。这就是如何使哈希具有重复键的方法。 - MS-AccessUnleashed

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接