哈希

最后更新于:2022-04-01 21:07:09

## 哈希是键/值对 如果你想按名字查询,那么需要哈希。哈希的键必须唯一,但值可以是任意标量。 有时候你仍然会看到人们称它为“关联数组”,但不要想当然的把它作为数组。 ## 通过键/值对列表来创建哈希 使用键/值对列表创建哈希: ~~~ my %stooges = ( 'Moe', 'Howard', 'Larry', 'Fine', 'Curly', 'Howard', 'Iggy', 'Pop', ); ~~~ `=>` 称为胖逗号,它与逗号相同,前面的单词加上引号: ~~~ my %stooges = ( Moe => 'Howard', Larry => 'Fine', Curly => 'Howard', Iggy => 'Pop', ); ~~~ 哈希在列表环境中变成键/值对列表。 ~~~ my @hash_as_an_array = %stooges; # Contains ( 'Curly', 'Haward', 'Larry', 'Fine', etc... ) ~~~ 正如哈希的键和值顺序事实上随机的一样,平展开的哈希键/值顺序也是随机的。 ## 利用花括号访问独立的哈希条目 利用花括号代替中括号来获取哈希的值。 ~~~ print $stooges{'Iggy'}; # Prints "Pop" ~~~ 用同样的方式设置值: ~~~ $stooges{'Shemp'} = 'Howard'; ~~~ 覆盖现有的值: ~~~ $stooges{'Iggy'} = 'Ignatowski'; ~~~ 从哈希中删除条目: ~~~ delete $stooges{'Curly'}; ~~~ 注意:`delete` 不会删除文件。`unlink` 才会。 ~~~ unlink $stooges{'Moe'}; # Deletes a file called 'Howard'; ~~~ ## 获取哈希的键/值 使用 `keys` 和 `values` 关键字: ~~~ my @stooge_first_names = keys %stooges; my @stooge_last_names = values %stooges; ~~~ 这会保证键和值的顺序相匹配。 ## 哈希键自引用单词 如果你的哈希键是单个词,那么你不需要引用它。 ~~~ $stooges{Curly} = 'Howard'; ~~~ ## 哈希只能包含标量 在 Perl 哈希中的值只能是标量。它不能包含数组或数组中的列表。 ~~~ $hash{comedians} = @stooges; # Assigns the length of @stooges to the value ~~~ 如果你想要在哈希中存储数组,你将需要使用引用。 ## 哈希是无序的 `keys %hash` 和 `values %hash` 的顺序实事上是随机的。每次执行程序都将不同。 它也与添加时的顺序不相关。 如果你想保留哈希元素添加时的顺序,那么可以使用 [Tie::IxHash](https://metacpan.org/module/Tie::IxHash) 模块。 ## 你无法排序哈希 在 Perl 中排序哈希的想法不存在,因为哈希是无序的。你可以排序哈希的键, 或哈希的值,它们只是列表而已。 ## 使用列表赋值合并哈希 要合并两个哈希,将它们看作列表,并赋给哈希。 ~~~ my %new_hash = (%hash1, %hash2); ~~~ 等号右边是来自两个哈希的键/值对长列表。然后将该列表赋给 `%new_hash`。 如果在`%hash2` 中的任意键与 `%hash1` 中的键重复,那么 `%hash2` 中的键/值 对具有更高的优先级,因为它们赋值更晚。 ## 何时使用哈希,何时使用数组 如果你做线性、有序的序列,那么使用数组。 * 要读取的文件列表 * 队列中的人列表 如果你做想要查询的无序的事,那么使用哈希。 * 姓索引,通过名字查询 * 显示文件大小的索引,按名称查询 ## `defined` 与 `exists` 的差异 使用 `defined` 来看哈希元素是否有 `undef` 之外的值。如果哈希元素有任意 `undef` 之外的值,甚至求值为假的 0 和 ""(空字符串),都将返回真。 使用 `exists` 来看哈希元素是否已被初始化,即便它没有被定义(如,它有值`undef`)。 ~~~ my %h; $h{'foo'} = undef; defined $h{'foo'} ? print 1 : print 0; # $h{'foo'} is not defined, so it prints 0 exists $h{'foo'} ? print 1 : print 0; # but it has been initialized nonetheless, and so this line prints 1 ~~~ 哈希元素仅被定义后才为真。它仅在存在后才能被定义。 然而,哈希元素未被定义仍能存在。这意味着即便它存在,也不会返回真。 ~~~ if ( $h{'foo'} ) { print 'true'; } else { print 'false'; } # prints 'false'; since $h{'foo'} is not defined, it cannot be true ~~~
';