2014-09-29 138 views
1

我们如何在Perl中检索哈希散列值中的键值? 我试图使用按键功能。我想删除重复项,然后对它们进行排序,我可以使用uniqsort函数做 。我错过了什么?Perl - 从散列哈希中检索值

#!/usr/bin/perl 

use warnings; 
use strict; 

sub ids { 
    my ($data) = @_; 

    my @allID = keys %{$data}; 

    my @unique = uniq @allID; 
    foreach (@unique) { 
     @allUniqueID = $_; 
    } 

    my @result = sort{$a<=>$b}(@allUniqueId); 
    return @result; 
} 

my $data = { 
    'first' => { 
     'second' => { 
      'third1' => [ 
       { id => 44, name => 'a', value => 'aa' }, 
       { id => 48, name => 'b', value => 'bb' }, 
       { id => 100, name => 'c', value => 'cc' } 
      ], 
      id => 19 
     }, 
     'third2' => [ 
      { id => 199, data => 'dd' }, 
      { id => 40, data => 'ee' }, 
      { id => 100, data => { name => 'f', value => 'ff' } } 
     ], 
     id => 55 
    }, 
    id => 1 
}; 

# should print “1, 19, 40, 44, 48, 55, 100, 199” 
print join(', ', ids($data)) . "\n"; 

我知道它不完整,但我不知道如何继续。任何帮助,将不胜感激。

回答

2

这个程序将递归走路的数据结构和拔出都对应一个哈希键id的价值观,没有对结果排序或消除重复:

sub all_keys { 
    my $obj = shift; 

    if (ref $obj eq 'HASH') { 
     return map { 
      my $value = $obj->{$_}; 
      $_ eq 'id' ? $value : ref $value ? all_keys($value) :(); 
     } keys %$obj; 

    } elsif (ref $obj eq 'ARRAY') { 
     return map all_keys($_), @$obj; 

    } else { 
     return; 
    } 
} 

来进行排序/消灭,只是这样称呼它:

my @ids = sort { $a <=> $b } uniq(all_ids($data)); 

(我假设uniq程序别处定义。)

+0

UNIQ是一个内置的,我使用的功能。 – abc 2014-09-29 06:42:41

+0

'uniq'在['List :: Util'](https://metacpan.org/module/List::Util) – Borodin 2014-09-29 08:57:35

0

这里是我的v该递归方法的版为

use warnings; 
use strict; 

sub ids { 
    my ($data) = @_; 

    my @retval; 
    if (ref $data eq 'HASH') { 
     push @retval, $data->{id} if exists $data->{id}; 
     push @retval, ids($_) for values %$data; 
    } 
    elsif (ref $data eq 'ARRAY') { 
     push @retval, ids($_) for @$data; 
    } 
    @retval; 
} 

my $data = { 
    'first' => { 
     'second' => { 
      'third1' => [ 
       { id => 44, name => 'a', value => 'aa' }, 
       { id => 48, name => 'b', value => 'bb' }, 
       { id => 100, name => 'c', value => 'cc' } 
      ], 
      id => 19 
     }, 
     'third2' => [ 
      { id => 199, data => 'dd' }, 
      { id => 40, data => 'ee' }, 
      { id => 100, data => { name => 'f', value => 'ff' } } 
     ], 
     id => 55 
    }, 
    id => 1 
}; 

my @ids = sort { $a <=> $b } ids($data); 
print join(', ', @ids), "\n"; 

输出

1, 19, 40, 44, 48, 55, 100, 100, 199 

更新

在上述方案中的代码的一个大的块是有来解决如何以提取数据引用中的值列表。最近版本的Perl有一个实验工具,它允许你在散列和数组上使用values运算符,并且也可以在两个引用上使用,所以如果你运行的是Perl 5的版本14或更高版本并且很好地禁用实验警告,那么你可以写ids这样反而

use warnings; 
use strict; 
use 5.014; 

sub ids { 
    my ($data) = @_; 
    return unless my $type = ref $data; 

    no warnings 'experimental'; 
    if ($type eq 'HASH' and exists $data->{id}) { 
     $data->{id}, map ids($_), values $data; 
    } 
    else { 
     map ids($_), values $data; 
    } 
} 

输出是等同于以前的解决方案