使用map创建哈希和数组

时间:2014-07-17 05:14:01

标签: perl

我是Perl的新手,我试图了解map功能。

my %names = qw (hanibal lecter Harry Potter INDIANA JONES Sarah connor scarlet O’Hara JAMES Bond);
my ($k, $v);
my @names;
while (($k,$v) = each %names) {
    my @name ;
    push(@name , $k);
    push(@name , $v);
    push(@names, \@name);
}
print "Unsorted names : \n";
foreach(0..$#names) {
    print "@{$names[$_]}\n";
} 

这样可以,并打印所有这样的名称

hanibal lecter
scarlet O¦Hara
Harry Potter
Sarah connor
INDIANA JONES
JAMES Bond

我修改了一些我的代码并知道它看起来像这样:

my %names = map { $_ } qw (hanibal lecter Harry Potter INDIANA JONES Sarah connor scarlet O’Hara JAMES Bond);
my ($k, $v);
my @names;
while (($k,$v) = each %names) {
    my @name = map {$k, $v} ($k,$v) ;
    #my @name;
    #push(@name , $k);
    #push(@name , $v);
    push(@names, \@name);
}
foreach(0..$#names) {
    print "@{$names[$_]}\n";
}

哈希是corectly创建的,但数组不是 输出是

hanibal lecter hanibal lecter
scarlet O▒Hara scarlet O▒Hara
Harry Potter Harry Potter
Sarah connor Sarah connor
INDIANA JONES INDIANA JONES
JAMES Bond JAMES Bond

为什么每条记录加倍?

4 个答案:

答案 0 :(得分:3)

Map通过迭代列表和每个元素生成一个新列表,调用一个代码块来为新列表生成元素。

你说:

my @name = map {$k, $v} ($k,$v) ;

导致{}中的代码被调用两次,一次用于括号列表中的$k,一次用于$v。因为您不在代码块中使用$_,所以除了确定调用代码块的次数之外,输入并不重要。您可以从

获得相同的结果
my @name = map {$k, $v} (1,2) ;

my @name = map {$k, $v} ( 'donkey', 'zebra' ) ;

每次调用代码块时,它都会返回一个包含两个元素的列表,其值为$k$v,因此map返回四个元素的列表,其值为{{1} }。

答案 1 :(得分:0)

你的哈希应该适用于此。如果您希望更好地直观地表示数据的作用,最好使用fat comma来执行此操作。例如:

my %names = ("hanibal" => "lecter",  "Harry" => "Potter", "INDIANA" => "JONES", 
             "Sarah" => "connor", "scarlet" => "OHara", "JAMES" => "Bond");

say "First name is $_ and last name is $names{$_}" for keys %names

输出:

First name is Sarah and last name is connor
First name is JAMES and last name is Bond
First name is hanibal and last name is lecter
First name is INDIANA and last name is JONES
First name is Harry and last name is Potter
First name is scarlet and last name is OHara

如果我误解了您的请求,请澄清。

答案 2 :(得分:0)

  

我已经阅读了很多关于地图的例子   none从数组创建一个哈希,我想怎么做(第一个   element是关键,第二个是值等等。)。

Map始终返回一个列表,该列表可以分配给哈希,使元素成为键/值对。有关详细信息,请参阅perldata

my %hash = map {split /,/} @array; 

Demo

相同
my %hash = @array; 

Demo


从哈希

创建数组
my @array = %hash;

Demo

答案 3 :(得分:0)

哈希只是键/值对的列表,所以当你这样做时

my %names = qw(hanibal lecter Harry Potter INDIANA JONES Sarah connor scarlet O’Hara JAMES Bond);

你已经有了一个完整的哈希:

%names = (
    hanibal => "lecter",
    Harry   => "Potter",
    INDIANA => "JONES",
    JAMES   => "Bond",
    Sarah   => "connor",
    scarlet => "O’Hara",
);

因此,如果您在尝试获得相同结果时对此应用map,则必须只创建已有的所有值的列表(映射身份函数):

my %hash = map { $_ } qw(...);

这当然毫无意义。当您需要列表中的元素转换为新列表时,请使用map。例如,如果要从正确大写的名称中创建哈希,可以执行以下操作:

my %names = map { ucfirst(lc($_)) } qw(...);

创建一个这样的哈希:

%names = {
    Hanibal => "Lecter",
    Harry   => "Potter",
    Indiana => "Jones",
    James   => "Bond",
    Sarah   => "Connor",
    Scarlet => "O’hara",
}

由于数组只是值列表而哈希是键列表=>对于列表运算符,它们可以在某种程度上互换使用。要从哈希中创建数组,只需执行:

my @array = %hash;

你通常不需要这样做,但是如果你想做一些事情,比如按字母顺序打印每个键/值对在它自己的行上,用空格分隔,最简单的做这样的事情:

my @full_names;
while (my ($key, $val) = each %names)
{
    push @full_names, "$key $val"; # Concatenate first and last names so they
}                                  # stick together when sorted
print join "\n", sort @full_names;