Perl 哈希
Perl - 哈希(Hashes)
Section titled “Perl - 哈希(Hashes)”Perl 中的哈希(hash)是键值对(key-value pair)的无序集合。在其他语言中,哈希也称为关联数组(associative arrays)或字典(dictionaries)。哈希变量名前缀是百分号(%),例如 %my_hash。要访问哈希中的单个元素(值),使用美元符号($)作为前缀,后跟哈希名称,然后是花括号中的键,例如 $my_hash{'some_key'},如果键是简单的裸字(bareword),也可以写作 $my_hash{some_key}。
Perl 哈希中的键(key)总是字符串。如果你使用数字作为键,Perl 会将其转换为字符串表示。值(value)可以是任何标量(scalar)(数字、字符串或引用)。
这里有一个简单的例子:
#!/usr/bin/perluse strict;use warnings;
my %student_ages = ( 'Alice' => 22, 'Bob' => 24, 'Charlie' => 21,);
print "Alice's age: $student_ages{'Alice'}\n";print "Bob's age: $student_ages{'Bob'}\n";
# Using bareword for key (if simple enough, quotes are optional with =>)# 使用裸字作为键(如果足够简单,=> 后可以省略引号)my %capitals = ( USA => "Washington D.C.", UK => "London", Japan => "Tokyo",);print "Capital of UK: $capitals{UK}\n";这将产生如下输出:
Alice's age: 22Bob's age: 24Capital of UK: London可以通过几种方式创建哈希:
- 逐个赋值键值对:
my %user_data;$user_data{'name'} = "David";$user_data{'id'} = 101;$user_data{'email'} = 'david@example.com';- 使用键值对列表: 列表被解释为交替的键和值。
my %contact_info = ('name', 'Eve', 'phone', '555-1234', 'city', 'New City');- 使用
=>(胖逗号,fat comma)操作符: 这是逗号的别名,但通过视觉上配对键和值来提高可读性。如果左侧操作数是一个裸字(bareword)(看起来像标识符的简单字符串),它也会自动加上引号。这是最常见和推荐的方式。
my %book_details = ( title => "The Modern Perl Handbook", author => "Perl Hacker", year => 2023, ISBN => "978-0123456789", # Keys are strings # 键是字符串);访问哈希元素
Section titled “访问哈希元素”要检索值,请使用 $ 标记(sigil)和哈希名称,后跟花括号中的键。如果键不存在,访问它将返回 undef(未定义)。
#!/usr/bin/perluse strict;use warnings;
my %config = ( host => "localhost", port => 8080, timeout => 30,);
print "Host: $config{'host'}\n";print "Port: $config{port}\n"; # Bareword key in access# 访问时使用裸字键
my $non_existent_value = $config{'user'}; # Key 'user' doesn't exist# 键 'user' 不存在if (defined $non_existent_value) { print "User: $non_existent_value\n";} else { print "User key is not defined.\n";}输出:
Host: localhostPort: 8080User key is not defined.提取切片(多个值)
Section titled “提取切片(多个值)”哈希切片(hash slice)允许你通过提供一个键列表,一次性从哈希中检索多个值。使用 @ 标记(sigil)(因为你将获得一个值列表)。
#!/usr/bin/perluse strict;use warnings;
my %fruit_colors = ( apple => "red", banana => "yellow", grape => "purple", orange => "orange",);
my @selected_keys = ('apple', 'grape', 'kiwi'); # 'kiwi' doesn't exist# 'kiwi' 不存在my @colors = @fruit_colors{@selected_keys};# or directly: my @colors = @fruit_colors{'apple', 'grape', 'kiwi'};# 或者直接:my @colors = @fruit_colors{'apple', 'grape', 'kiwi'};
print "Colors found: " . join(", ", grep { defined } @colors) . "\n";# grep filters out undef for non-existent keys# grep 过滤掉不存在键对应的 undef 值# For 'kiwi', its corresponding value in @colors will be undef.# 对于 'kiwi',其在 @colors 中对应的值将是 undef。输出:
Colors found: red, purplekeys %HASH 函数返回哈希中所有键的列表(顺序看似随机)。values %HASH 函数返回所有值的列表(如果在同一个未修改的哈希上调用,其顺序与 keys %HASH 返回的对应键的顺序相同)。
#!/usr/bin/perluse strict;use warnings;
my %days_in_month = ( January => 31, February => 28, # Ignoring leap years for simplicity # 为简单起见,忽略闰年 March => 31,);
my @months = keys %days_in_month;print "Months: " . join(", ", sort @months) . "\n";
my @num_days = values %days_in_month;print "Number of days (in some order): " . join(", ", @num_days) . "\n";# 天数(顺序不定):...
# Iterating over key-value pairs# 迭代键值对while (my ($month, $days) = each %days_in_month) { print "$month has $days days.\n"; # $month 有 $days 天。}# Note: `each` iterates in an apparently random order. Modifying the hash while iterating with `each` can lead to issues.# 注意:`each` 以看似随机的顺序迭代。在使用 `each` 迭代时修改哈希可能导致问题。输出(未排序的键/值和 each 的顺序可能会有所不同):
Months: February, January, MarchNumber of days (in some order): 28, 31, 31January has 31 days.March has 31 days.February has 28 days.检查键是否存在
Section titled “检查键是否存在”exists $HASH{key} 函数返回真,如果指定的键存在于哈希中,即使其值为 undef。这与检查 defined $HASH{key} 不同,后者检查与键关联的值是否已定义。
#!/usr/bin/perluse strict;use warnings;
my %settings = ( user => "admin", level => 5, theme => undef, # Key exists, but value is undef # 键存在,但值为 undef);
if (exists $settings{'theme'}) { print "'theme' key exists.\n"; # 'theme' 键存在。} else { print "'theme' key does not exist.\n"; # 'theme' 键不存在。}
if (defined $settings{'theme'}) { print "Value for 'theme' is defined: $settings{'theme'}\n"; # 'theme' 的值已定义:...} else { print "Value for 'theme' is not defined (it's undef).\n"; # 'theme' 的值未定义(它是 undef)。}
if (exists $settings{'password'}) { print "'password' key exists.\n"; # 'password' 键存在。} else { print "'password' key does not exist.\n"; # 'password' 键不存在。}输出:
'theme' key exists.Value for 'theme' is not defined (it's undef).'password' key does not exist.获取哈希大小
Section titled “获取哈希大小”要查找哈希中键值对的数量,可以在标量上下文(scalar context)中评估哈希,或在标量上下文评估 keys %HASH 或 values %HASH。最直接的方法通常是 scalar %HASH,如果哈希确定包含键值对,但 scalar keys %HASH 非常常见且明确。
#!/usr/bin/perluse strict;use warnings;
my %inventory = ( apples => 100, bananas => 150, oranges => 75,);
my $num_items_method1 = scalar(keys %inventory);print "Number of item types (method 1): $num_items_method1\n";# 项目类型数量(方法 1):...
# In scalar context, a hash used in a numeric context returns true if it has elements, false otherwise.# 在标量上下文中,在数字上下文使用的哈希,如果包含元素则返回真,否则返回假。# To get the count of pairs, you usually use keys or values in scalar context.# 要获取键值对的数量,通常在标量上下文中使用 keys 或 values。# A more idiomatic way to get the count of keys:# 获取键数量更惯用的方式:my $key_count = keys %inventory; # In scalar context, keys returns number of keys# 在标量上下文中,keys 返回键的数量print "Number of item types (method 2): $key_count\n";# 项目类型数量(方法 2):...
# If a hash is empty, scalar context returns false (empty string or 0 depending on use)# 如果哈希为空,标量上下文返回假(取决于用法,可能是空字符串或 0)my %empty_hash;if (%empty_hash) { print "Empty hash is true in boolean context (this won't print for truly empty hash after Perl 5.22)\n"; # 空哈希在布尔上下文为真(对于 Perl 5.22 之后的空哈希,这不会打印)} else { print "Empty hash is false in boolean context.\n"; # 空哈希在布尔上下文为假。}# Prior to Perl 5.22, an empty hash in boolean scalar context was true.# 在 Perl 5.22 之前,空哈希在布尔标量上下文中为真。# From 5.22 onwards, it's false. This behavior was somewhat problematic.# 从 5.22 开始,它为假。此行为之前有些问题。# The reliable way to check for emptiness is `if (keys %empty_hash)`.# 检查哈希是否为空的可靠方法是 `if (keys %empty_hash)`。输出:
Number of item types (method 1): 3Number of item types (method 2): 3Empty hash is false in boolean context.在哈希中添加和移除元素
Section titled “在哈希中添加和移除元素”使用简单的赋值添加或更新键值对:$HASH{new_key} = $value;。要移除键值对,使用 delete $HASH{key} 函数。delete 返回与被删除键关联的值(如果键不存在则返回 undef)。
#!/usr/bin/perluse strict;use warnings;use Data::Dumper; # For pretty-printing the hash# 用于美化打印哈希
my %employee_data = ( 101 => "Alice", 102 => "Bob",);print "Initial: " . Dumper(\%employee_data);# 初始:...
# Add a new employee# 添加新员工$employee_data{103} = "Charlie";print "After add: " . Dumper(\%employee_data);# 添加后:...
# Update an existing employee's name# 更新现有员工姓名$employee_data{101} = "Alicia";print "After update: " . Dumper(\%employee_data);# 更新后:...
# Remove an employee# 移除员工my $deleted_value = delete $employee_data{102};print "Deleted Bob. Value was: $deleted_value\n";# 已删除 Bob。值曾是:...print "After delete: " . Dumper(\%employee_data);# 删除后:...输出(Dumper 的具体格式可能略有不同):
Initial: $VAR1 = { '101' => 'Alice', '102' => 'Bob' };After add: $VAR1 = { '101' => 'Alice', '102' => 'Bob', '103' => 'Charlie' };After update: $VAR1 = { '101' => 'Alicia', '102' => 'Bob', '103' => 'Charlie' };Deleted Bob. Value was: BobAfter delete: $VAR1 = { '101' => 'Alicia', '103' => 'Charlie' };