任何人都可以解释为什么foreach工作但不映射

Jas*_*ssi 2 perl hash exists map

如果密钥存在于%hash中,我试图将键值对放在%hash1上.数组中有一个元素,%hash ex上没有条目:@array =(1,2,3,4,5); #there在%hash处没有密钥1的哈希条目

所以我认为map会完成这项工作,我会在我的新哈希中获得4个键,即%hash1,但它会提供5个键.与此同时,我尝试了foreach并且它起作用了.我妄想我们可以用地图取代foreach,但这个案例让我思考.谁能解释一下,我的逻辑出错了?

#Method 1. Comment it while using Method 2
%hash1 = map { $_=>$hash{$_}  if(exists $hash{$_}) } @array;

# Method 2. Comment whole loop while using method 1
foreach (@array){
    $hash1{$_} = $hash{$_} if(exists $hash{$_});
}
Run Code Online (Sandbox Code Playgroud)

Dav*_*oss 9

你的问题是你的map表达式undef为第一个元素返回一个false值@array.并且它被字符串化为空字符串,因为它被用作散列键. (在评论中,Borodin指出这种解释是不正确的.事实上,空字符串来自于exists键为"1"时返回的false值)

如果你一)打开你可能会得到一个什么样正在做一个更好的主意strict,并warnings和b)使用Data::Dumper显示散列一旦你创建它.

#!/usr/bin/perl

use strict;
use warnings;
use 5.010;

use Data::Dumper;

my @array = (1 .. 5);
my %hash = ( 2 => 'two', 3 => 'three', 4 => 'four', 5 => 'five' );

my %hash1 = map { $_=>$hash{$_}  if(exists $hash{$_}) } @array;

say Dumper \%hash1;
Run Code Online (Sandbox Code Playgroud)

这表明你最终得到这样的哈希:

$ ./hash 

Odd number of elements in hash assignment at ./hash line 12.
$VAR1 = {
          '' => 2,
          'three' => 4,
          'five' => undef,
          'two' => 3,
          'four' => 5
        };
Run Code Online (Sandbox Code Playgroud)

您正在生成具有奇数个元素的列表.这并没有令人愉快的哈希.

在构建哈希时,您需要确保拥有偶数个元素.因此,当您使用时,map您需要为每次迭代返回零或两个元素.所以你需要这样的东西:

#!/usr/bin/perl

use strict;
use warnings;
use 5.010;

use Data::Dumper;

my @array = (1 .. 5);
my %hash = ( 2 => 'two', 3 => 'three', 4 => 'four', 5 => 'five' );

my %hash1 = map { exists $hash{$_} ? ($_ => $hash{$_}) : () } @array;

say Dumper \%hash1;
Run Code Online (Sandbox Code Playgroud)

请注意,当在第一个哈希中找不到键时,我们显式返回一个空列表.

$ ./hash2
$VAR1 = {
          '4' => 'four',
          '3' => 'three',
          '2' => 'two',
          '5' => 'five'
        };
Run Code Online (Sandbox Code Playgroud)

  • 你对`undef`被字符串化为空字符串的解释是*错*.您看到的空字符串是不存在的键的"exists $ hash {$ _}"的值.如果没有"使用未初始化的值"警告噪声,`undef`将不会转换为空字符串. (7认同)