Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Perl中将具有相同键的散列值转换为数组的散列_Perl_Data Structures_Hashtable_Associative Array_Perl Data Structures - Fatal编程技术网

在Perl中将具有相同键的散列值转换为数组的散列

在Perl中将具有相同键的散列值转换为数组的散列,perl,data-structures,hashtable,associative-array,perl-data-structures,Perl,Data Structures,Hashtable,Associative Array,Perl Data Structures,我需要在perl中将散列转换为数组的散列 我有: %hash = ( tinku => 15, tina => 4, rita => 18, tinku => 18, tinku => 17, tinku => 16, rita => 19 ); 我想把它改成: %hash = ( tinku => [ 15, 16, 17, 18 ], rita => [ 18, 19 ],

我需要在perl中将散列转换为数组的散列

我有:

%hash = (
    tinku => 15,
    tina  => 4,
    rita  => 18,
    tinku => 18,
    tinku => 17,
    tinku => 16,
    rita  => 19
);
我想把它改成:

%hash =  ( tinku => [ 15, 16, 17, 18 ], rita => [ 18, 19 ], tina => 4 );

你一开始就不能吃那种杂烩。Perl中的散列必须具有唯一的键。

首先不能具有该散列。Perl中的散列必须具有唯一的键。

你在要求不可能的东西!哈希只能有唯一的键,因此在您的示例中,您将生成一个哈希,该哈希将每个唯一名称作为其键,并将每个键的最后一个值作为其值:

#!/usr/bin/perl
use warnings;
use strict; 
use Data::Dumper;

my %hash = (tinku =>15,tina =>4, rita =>18, 
           tinku =>18, tinku =>17, tinku =>16, rita =>19);

print Dumper \%hash;

要对数组进行散列,可以尝试以下操作:

my %hash;

my @names = qw(tinku tina rita tinku tinku tinku rita);
my @nums = qw(15 4 18 18 17 16 19);


push @{ $hash{ $names[$_] } }, $nums[$_] for 0 .. $#names;


print Dumper \%hash;


你在要求不可能的事!哈希只能有唯一的键,因此在您的示例中,您将生成一个哈希,该哈希将每个唯一名称作为其键,并将每个键的最后一个值作为其值:

#!/usr/bin/perl
use warnings;
use strict; 
use Data::Dumper;

my %hash = (tinku =>15,tina =>4, rita =>18, 
           tinku =>18, tinku =>17, tinku =>16, rita =>19);

print Dumper \%hash;

要对数组进行散列,可以尝试以下操作:

my %hash;

my @names = qw(tinku tina rita tinku tinku tinku rita);
my @nums = qw(15 4 18 18 17 16 19);


push @{ $hash{ $names[$_] } }, $nums[$_] for 0 .. $#names;


print Dumper \%hash;

此赋值只保留每个键的最后一个值(即tinku=>16,rita=>19,tina=>4),并忽略前面的值。这样做是为了允许在散列赋值中重写值。例如

sub some_function {
     my %args = (%sane_defaults, @_);
};
而且,(foo=>(1,2,3))将创建散列(foo=>1,2=>3),而不是您所期望的

一个可能的解决办法是:

use strict;
use warnings;
use Data::Dumper;

my @array = (tinku =>15,tina =>4, rita =>18, tinku =>18, 
     tinku =>17, tinku =>16, rita =>19);
my %hash = hash_of_arrays( @array );
print Dumper(\%hash);

sub hash_of_arrays {
     die "Odd number of elements in hash (of arrays) assignment"
          if @_ % 2;
     # I never understood why this is a *warning* :-)

     # populate hash by hand
     my %hash; 
     while (@_) {
          my $key = shift;
          my $value = shift;
          push @{ $hash{$key} }, $value;
          # here hash values automatically become 
          # empty arrayrefs if not defined, thanks Larry
     };
     return %hash; 
     # *tecnically*, this one returns *array* 
     # and converts it back to hash
};
此赋值只保留每个键的最后一个值(即tinku=>16,rita=>19,tina=>4),并忽略前面的值。这样做是为了允许在散列赋值中重写值。例如

sub some_function {
     my %args = (%sane_defaults, @_);
};
而且,(foo=>(1,2,3))将创建散列(foo=>1,2=>3),而不是您所期望的

一个可能的解决办法是:

use strict;
use warnings;
use Data::Dumper;

my @array = (tinku =>15,tina =>4, rita =>18, tinku =>18, 
     tinku =>17, tinku =>16, rita =>19);
my %hash = hash_of_arrays( @array );
print Dumper(\%hash);

sub hash_of_arrays {
     die "Odd number of elements in hash (of arrays) assignment"
          if @_ % 2;
     # I never understood why this is a *warning* :-)

     # populate hash by hand
     my %hash; 
     while (@_) {
          my $key = shift;
          my $value = shift;
          push @{ $hash{$key} }, $value;
          # here hash values automatically become 
          # empty arrayrefs if not defined, thanks Larry
     };
     return %hash; 
     # *tecnically*, this one returns *array* 
     # and converts it back to hash
};

因为散列只能有唯一的键,所以不要将列表分配给散列,而是使用from进行处理

输出

$VAR1 = {
      'tinku' => [
                   15,
                   18,
                   17,
                   16
                 ],
      'rita' => [
                  18,
                  19
                ],
      'tina' => [
                  4
                ]
    };

因为散列只能有唯一的键,所以不要将列表分配给散列,而是使用from进行处理

输出

$VAR1 = {
      'tinku' => [
                   15,
                   18,
                   17,
                   16
                 ],
      'rita' => [
                  18,
                  19
                ],
      'tina' => [
                  4
                ]
    };

这里的其他响应中所涵盖的技术和模式都是经过实践检验的、真正的习惯用法,对于充分利用Perl、理解现有代码以及使用大量较旧的Perl编译器是必不可少的。只是为了好玩
我想我还提到了一些其他方法:

perl-5.22
中有一个可读性很强的新语法,它可以替代。我要说一些更时髦的东西。Perl6还提供了一种很好的方法,可以将具有潜在非唯一键的键/值对列表转换为包含具有多个值的键的散列

正如其他回应所指出的,所有这些的“关键”是:

要使散列键引用多个值,这些值不仅需要是列表或数组,还需要是匿名数组
[]
或引用


使用
perl-5.22提供的新语法
显示了标准的Perl习惯用法。正在使用0的
遍历
@names
$#名称
确保重叠键不会“丢失”,而是指向多个值的匿名数组。使用
perl-5.22
我们可以使用
List::Util
(核心模块)中的
pairs()
函数,将键/值对添加到哈希中,并以稍微不同的方式解释重叠或重复的键:

use experimental qw(postderef);
use List::Util qw/pairs/;

my %hash;    
my $a_ref = [ qw/tinku 15 tina 4 rita 18 tinku 18 tinku 17 tinku 16 rita 19/ ];
push $hash{$_->key}->@* , $_->value for pairs @$a_ref;

use DDP;
p %hash;
从1.39版开始,List::Util::pairs()
将数组引用作为可通过
->key
->value
方法访问的对象返回。该示例使用了LEONT的pragma,使内容更加紧凑

输出:

{
    rita    [
        [0] 18,
        [1] 19
    ],
    tina    [
        [0] 4
    ],
    tinku   [
        [0] 15,
        [1] 18,
        [2] 17,
        [3] 16
    ]
}
{:rita(["18", "19"]), :tina("4"), :tinku(["15", "18", "17", "16"])}<>
至于哪一种更具“可读性”:很难击败容易“摸索”的标准方法,但通过最新版本的perl5中提供的新语法,我们可以探索新习语的潜力。我真的开始喜欢后缀解引用了。TIMTOWTDI和更远的地方


@宫川的
Hash::MultiValue
有了这个模块,您就可以创建一个
Hash::MultiValue
对象(有许多方法以各种方式访问它)和一个简单的Hash引用,以方便地处理每个键的多个值

#!/usr/bin/env perl -l
use Hash::MultiValue;
use strict;
use warnings;

my $mvhash = Hash::MultiValue->new(tinku =>15, tina =>4, rita =>18,
                tinku =>18, tinku =>17, tinku =>16, rita =>19);

print "\ntinku's values:\n", join " ", $mvhash->get_all('tinku');

print "\nflattened mvhash:\n", join " ", $mvhash->flatten ;

print "\n ... using mvhash as a hashref:" ;
print join " ", $mvhash->get_all($_) for keys %$mvhash ;

print "\n", '... as a "mixed" hashref with each():';
my $mvhash_ref = $mvhash->mixed ;

while ( my ($k, $v) = each $mvhash_ref ) { 
  print "$k => " , ref $v eq "ARRAY" ? "@{$v}" : "$v" ; 
}
输出:

{
    rita    [
        [0] 18,
        [1] 19
    ],
    tina    [
        [0] 4
    ],
    tinku   [
        [0] 15,
        [1] 18,
        [2] 17,
        [3] 16
    ]
}
{:rita(["18", "19"]), :tina("4"), :tinku(["15", "18", "17", "16"])}<>
tinku的价值观:
15 18 17 16
平铺mvhash:
tinku 15 tina 4 rita 18 tinku 18 tinku 17 tinku 16 rita 19
... 使用mvhash作为hashref:
15 18 17 16
18 19
4.
... 将hashref与each()混合使用:
tinku=>15 18 17 16
丽塔=>18 19
蒂娜=>4
一旦您的散列作为
hash::MultiValue
对象可用,您就可以通过各种方式对其进行操作,以快速创建临时副本和散列引用。只需将它们分配到标量和
Dump
the(或使用
DDP
)即可了解其工作原理:

use DDP; 
my $hmulti = $mvhash->multi; p $hmulti ;
my $hmixed = $mvhash->mixed; p $hmixed 
hash::multi-value
对象使用常规哈希操作有一些限制(像
dd\$mvhash
这样的东西不会显示整个哈希-您需要执行
dd$hash->multi
),但是在某些情况下,以这种方式使用多值哈希是有好处的(即,某些功能所需的可读性更强和/或代码可能更少)

您仍然需要识别何时/何地
Hash::MultiValue
是有用的,因此它不是明确的“更容易”或“更干净”——但它是对perl工具的另一个有用的补充


Perl 6-仅供比较 Perl6对于从列表中获取键/值对来说更为紧凑,因为您可以使用,按元素组遍历列表,然后使用
push
将它们排列成散列。您可以通过“自动”解释重叠键的方式来执行此操作。参见此简短的Perl6片段:

my %h ;
for <tinku 15 tina 4 rita 18 tinku 18 tinku 17 tinku 16 rita 19> -> $k, $v { 
    %h.push($k => $v) ;
}
%h.perl.say ;
输出:

{
    rita    [
        [0] 18,
        [1] 19
    ],
    tina    [
        [0] 4
    ],
    tinku   [
        [0] 15,
        [1] 18,
        [2] 17,
        [3] 16
    ]
}
{:rita(["18", "19"]), :tina("4"), :tinku(["15", "18", "17", "16"])}<>
{:rita([“18”、“19”),:tina(“4”),:tinku([“15”、“18”、“17”、“16”)}

比照

  • 示例脚本
不仅仅是继续开发
perl
编译器使编写perl-co成为可能