热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

将具有相同键的哈希值转换为Perl中的数组哈希值

如何解决《将具有相同键的哈希值转换为Perl中的数组哈希值》经验,为你挑选了2个好方法。

我需要将哈希转换为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 );

Dallaylaen.. 5

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

这个赋值只保留每个键的最后一个值(即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
};


G. Cito.. 5

这里的其他响应所涵盖的技术和模式都经过了尝试和真正的习惯用法,这对于充分利用Perl,理解现有代码以及使用旧的perl编译器的大型安装基础至关重要.只是为了好玩,我想我提到了几个其他方法:

有一个相当可读的新语法,perl-5.22它是@fugu采用更经典方法的替代方法.对于更加时髦的东西,我会提到@ miyagawa的 Hash::MultiValue.Perl 6还有一种很好的方法可以将具有潜在非唯一键的键/值对列表转换为包含具有多个值的键的哈希.

正如其他回应指出的那样,所有这一切的"关键"是:

对于引用多个值的哈希键,值不仅需要是列表或数组,还需要是匿名数组[ ]或引用.


使用新的语法 perl-5.22

Fugu的回应显示了标准的Perl习语.通过@names使用进行迭代for 0 .. $#names 可确保重叠键不会"丢失",而是指向多个值的匿名数组.与perl-5.22我们可以使用pairs()从函数List::Util(核心模块)和后缀解除引用到键/值对在一个稍微不同的方式添加到哈希和帐户用于重叠或重复的键:

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()返回ARRAY引用作为通过->key->value方法可访问的祝福对象.这个例子使用LEONTexperimental.pmpragma DDP并使事情变得更紧凑.

输出:

{
    rita    [
        [0] 18,
        [1] 19
    ],
    tina    [
        [0] 4
    ],
    tinku   [
        [0] 15,
        [1] 18,
        [2] 17,
        [3] 16
    ]
}

至于哪个更"可读":很难击败简单的"可移动"标准方法,但是使用最新版本的perl5中提供的新语法,我们可以探索新习语的潜力.我真的开始喜欢postfix dereferencing.TIMTOWTDI及其他!


@宫川的 Hash::MultiValue

使用此模块,您可以创建一个Hash::MultiValue对象(有许多方法可以通过各种方式访问​​它)和一个普通的哈希引用,以方便地使用每个键的多个值.

#!/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" ; 
}

输出:

tinku's values:
15 18 17 16

flattened mvhash:
tinku 15 tina 4 rita 18 tinku 18 tinku 17 tinku 16 rita 19

... using mvhash as a hashref:
15 18 17 16
18 19
4

... as a "mixed" hashref with each():
tinku => 15 18 17 16
rita => 18 19
tina => 4

一旦您的哈希作为Hash::MultiValue对象可用,您就可以通过各种方式对其进行操作,以快速创建临时副本和哈希引用.只需将它们分配给标量和Dump(或使用DDP)以了解它是如何工作的:

use DDP; 
my $hmulti = $mvhash->multi; p $hmulti ;
my $hmixed = $mvhash->mixed; p $hmixed 

对一个Hash::MultiValue对象使用常规哈希操作有一些限制(类似dd \$mvhash的事情不会向你显示整个哈希 - 你需要这样做dd $hash->multi)但是在某些情况下以这种方式处理多值哈希是有利的(某些功能需要更多可读和/或可能更少的代码.

你仍然需要识别何时/何时Hash::MultiValue有用,因此它并不是毫不含糊地"更容易"或"更清洁" - 但它是你的perl工具盒的另一个有用的补充.


Perl 6 - 仅供比较

Perl6对于从列表中获取键/值对可以更紧凑,因为您可以在for语句中使用"多个参数",通过元素组遍历列表然后使用push它们将它们排列成哈希.您可以通过"自动"考虑重叠键的方式执行此操作.比照 这个简短的perl6片段:

my %h ;
for  -> $k, $v { 
    %h.push($k => $v) ;
}
%h.perl.say ;

编辑: 友好的人们#perl6建议一个更简洁的"方法":

my %h.push: .pairup ;
%h.perl.say ;

输出:

{:rita(["18", "19"]), :tina("4"), :tinku(["15", "18", "17", "16"])}<>

比照

Miyagawa本人回答了关于Hash::MultiValue使用的问题.

我提到的另一个答案Hash::MultiValue.

讨论一些"新的"perl6函数(flip/reverse/invert)以及它们如何应用于哈希.

一个示例脚本使用Hash::MultiValue安全地反转散列

不仅仅是perl编译器的继续开发使得以新的和有趣的方式编写Perl代码成为可能.感谢@miygawa和Paul Evans对Scalar-List-Utils的管理,Hash::MultiValue即使您的版本perl与版本5.8一样久,也可以做很酷的事情.您可以尝试在最新版本中提供的功能List::Util,即使您perl是很少从这个千年(List::Util可与perl-5.6它迎来了21世纪的2000年3月).



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

这个赋值只保留每个键的最后一个值(即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
};



2> G. Cito..:

这里的其他响应所涵盖的技术和模式都经过了尝试和真正的习惯用法,这对于充分利用Perl,理解现有代码以及使用旧的perl编译器的大型安装基础至关重要.只是为了好玩,我想我提到了几个其他方法:

有一个相当可读的新语法,perl-5.22它是@fugu采用更经典方法的替代方法.对于更加时髦的东西,我会提到@ miyagawa的 Hash::MultiValue.Perl 6还有一种很好的方法可以将具有潜在非唯一键的键/值对列表转换为包含具有多个值的键的哈希.

正如其他回应指出的那样,所有这一切的"关键"是:

对于引用多个值的哈希键,值不仅需要是列表或数组,还需要是匿名数组[ ]或引用.


使用新的语法 perl-5.22

Fugu的回应显示了标准的Perl习语.通过@names使用进行迭代for 0 .. $#names 可确保重叠键不会"丢失",而是指向多个值的匿名数组.与perl-5.22我们可以使用pairs()从函数List::Util(核心模块)和后缀解除引用到键/值对在一个稍微不同的方式添加到哈希和帐户用于重叠或重复的键:

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()返回ARRAY引用作为通过->key->value方法可访问的祝福对象.这个例子使用LEONTexperimental.pmpragma DDP并使事情变得更紧凑.

输出:

{
    rita    [
        [0] 18,
        [1] 19
    ],
    tina    [
        [0] 4
    ],
    tinku   [
        [0] 15,
        [1] 18,
        [2] 17,
        [3] 16
    ]
}

至于哪个更"可读":很难击败简单的"可移动"标准方法,但是使用最新版本的perl5中提供的新语法,我们可以探索新习语的潜力.我真的开始喜欢postfix dereferencing.TIMTOWTDI及其他!


@宫川的 Hash::MultiValue

使用此模块,您可以创建一个Hash::MultiValue对象(有许多方法可以通过各种方式访问​​它)和一个普通的哈希引用,以方便地使用每个键的多个值.

#!/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" ; 
}

输出:

tinku's values:
15 18 17 16

flattened mvhash:
tinku 15 tina 4 rita 18 tinku 18 tinku 17 tinku 16 rita 19

... using mvhash as a hashref:
15 18 17 16
18 19
4

... as a "mixed" hashref with each():
tinku => 15 18 17 16
rita => 18 19
tina => 4

一旦您的哈希作为Hash::MultiValue对象可用,您就可以通过各种方式对其进行操作,以快速创建临时副本和哈希引用.只需将它们分配给标量和Dump(或使用DDP)以了解它是如何工作的:

use DDP; 
my $hmulti = $mvhash->multi; p $hmulti ;
my $hmixed = $mvhash->mixed; p $hmixed 

对一个Hash::MultiValue对象使用常规哈希操作有一些限制(类似dd \$mvhash的事情不会向你显示整个哈希 - 你需要这样做dd $hash->multi)但是在某些情况下以这种方式处理多值哈希是有利的(某些功能需要更多可读和/或可能更少的代码.

你仍然需要识别何时/何时Hash::MultiValue有用,因此它并不是毫不含糊地"更容易"或"更清洁" - 但它是你的perl工具盒的另一个有用的补充.


Perl 6 - 仅供比较

Perl6对于从列表中获取键/值对可以更紧凑,因为您可以在for语句中使用"多个参数",通过元素组遍历列表然后使用push它们将它们排列成哈希.您可以通过"自动"考虑重叠键的方式执行此操作.比照 这个简短的perl6片段:

my %h ;
for  -> $k, $v { 
    %h.push($k => $v) ;
}
%h.perl.say ;

编辑: 友好的人们#perl6建议一个更简洁的"方法":

my %h.push: .pairup ;
%h.perl.say ;

输出:

{:rita(["18", "19"]), :tina("4"), :tinku(["15", "18", "17", "16"])}<>

比照

Miyagawa本人回答了关于Hash::MultiValue使用的问题.

我提到的另一个答案Hash::MultiValue.

讨论一些"新的"perl6函数(flip/reverse/invert)以及它们如何应用于哈希.

一个示例脚本使用Hash::MultiValue安全地反转散列

不仅仅是perl编译器的继续开发使得以新的和有趣的方式编写Perl代码成为可能.感谢@miygawa和Paul Evans对Scalar-List-Utils的管理,Hash::MultiValue即使您的版本perl与版本5.8一样久,也可以做很酷的事情.您可以尝试在最新版本中提供的功能List::Util,即使您perl是很少从这个千年(List::Util可与perl-5.6它迎来了21世纪的2000年3月).


推荐阅读
  • rust编程这篇文章是关于我通过解决Twitch上尚未解决的所有CtCI问题来学习Rust的经验。英国科学博物馆集团AdaLovelace的肖像Rust徽标,由Moz ... [详细]
  • 本文介绍了作者在开发过程中遇到的问题,即播放框架内容安全策略设置不起作用的错误。作者通过使用编译时依赖注入的方式解决了这个问题,并分享了解决方案。文章详细描述了问题的出现情况、错误输出内容以及解决方案的具体步骤。如果你也遇到了类似的问题,本文可能对你有一定的参考价值。 ... [详细]
  • 本文介绍了在CentOS上安装Python2.7.2的详细步骤,包括下载、解压、编译和安装等操作。同时提供了一些注意事项,以及测试安装是否成功的方法。 ... [详细]
  • 操作系统RetHat9.0,存储设备华为3comEX1000在linux上建立能够识别盘阵的方法有三种1、HBA卡;2、TOE卡;3、is ... [详细]
  • 本文介绍了Python高级网络编程及TCP/IP协议簇的OSI七层模型。首先简单介绍了七层模型的各层及其封装解封装过程。然后讨论了程序开发中涉及到的网络通信内容,主要包括TCP协议、UDP协议和IPV4协议。最后还介绍了socket编程、聊天socket实现、远程执行命令、上传文件、socketserver及其源码分析等相关内容。 ... [详细]
  • SpringBoot uri统一权限管理的实现方法及步骤详解
    本文详细介绍了SpringBoot中实现uri统一权限管理的方法,包括表结构定义、自动统计URI并自动删除脏数据、程序启动加载等步骤。通过该方法可以提高系统的安全性,实现对系统任意接口的权限拦截验证。 ... [详细]
  • 本文介绍了Perl的测试框架Test::Base,它是一个数据驱动的测试框架,可以自动进行单元测试,省去手工编写测试程序的麻烦。与Test::More完全兼容,使用方法简单。以plural函数为例,展示了Test::Base的使用方法。 ... [详细]
  • 本文介绍了计算机网络的定义和通信流程,包括客户端编译文件、二进制转换、三层路由设备等。同时,还介绍了计算机网络中常用的关键词,如MAC地址和IP地址。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • Java各个版本新特性及Lambda表达式简介
    本文介绍了Java各个版本的新特性,包括接口的默认方法和Lambda表达式。接口的默认方法允许给接口添加非抽象的方法实现,使用default关键字。Lambda表达式提供了更简洁的语法,可以替代传统的匿名对象的方式。同时,还介绍了Lambda表达式在排序中的应用。 ... [详细]
  • Bro是一款强大的网络安全工具,以及协议识别与统计的工具。Broisapowerfulnetworkanalysisframeworkthatismuchdifferentfro ... [详细]
  • linux下连接mysql参数怎么设置的简单介绍
    本文目录一览:1、Linux下mysql允许远程连接怎么设置 ... [详细]
  • dataguard日志传输模式解析_SOFAJRaft 日志复制pipeline 实现剖析 | SOFAJRaft 实现原理
    SOFAStack(ScalableOpenFinancialArchitectureStack)是蚂蚁金服自主研发的金融级分布式架构,包 ... [详细]
  • HTML5Canvas图像模糊如何解决
    本文主要和大家介绍HTML5Canvas图像模糊完美解决办法,需要的朋友可以参考下,希望能帮助到大家。1、最近在用h5的canvas画动画,发现图像 ... [详细]
  • Map主要用于存储健值对,根据键得到值,因此不允许键重复(重复了覆盖了),但允许值重复hashMap是hashtable的轻量级实现(非线程安全的实现),他们都完成了Map接口,主要区 ... [详细]
author-avatar
tengfei2008
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有