如何在perl数据结构中获取一个键的所有值?

如何在perl数据结构中获取一个键的所有值?,perl,hash,Perl,Hash,我想写一个函数,它将返回下面任何级别的数据结构中所有“id”值的列表,按数字排序。此外,如果在数据结构中的多个位置发现相同的值,则该值只应包含在返回的列表中一次 sub ids {
 my ($data) = @_;
 
 # Define this function 
 } 
 
 my $data = {
 'top' => { 'window' => {

我想写一个函数,它将返回下面任何级别的数据结构中所有“id”值的列表,按数字排序。此外,如果在数据结构中的多个位置发现相同的值,则该值只应包含在返回的列表中一次

sub ids {
        
    my ($data) = @_;
       
        
    # Define this function

    }


    
    my $data = {
        
'top' => {
        'window' => {
            'elements' => {
                { id => 44, name => 'link', value => 'www.cnn.com' },

                    { id => 48, name => 'title', value => 'CNN Home Page' },
    
                { id => 100, name => 'author', value => 'Admin' }
    
            },

                id => 19

            },

            'cache' => {

                { id => 199, data => '5' },

                { id => 40, data => '9' },
    
            { id => 100, data => { name => 'author', value => 'Admin' }
 }
            },
    
        id => 55
    },

        id => 1  

    };

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

一些数据结构应该是数组,而不是OP中的散列

use strict;
use warnings;

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

  return map { 
    my $r = ref($data->{$_});
    $r eq "HASH" ? ids_r($data->{$_}) :
      $r         ? map ids_r($_), @{$data->{$_}} :
      $_ eq "id" ? $data->{$_} :
      ();
   } keys %$data;
}
sub ids {        
  my ($data) = @_;
  my %seen;
  return
    sort { $a <=> $b }
    grep !$seen{$_}++, ids_r($data);
}
my $data = {        
  'top' => {
    'window' => {
        'elements' => [
            { id => 44, name => 'link', value => 'www.cnn.com' },
            { id => 48, name => 'title', value => 'CNN Home Page' },
            { id => 100, name => 'author', value => 'Admin' }    
        ],
        id => 19
    },
    'cache' => [
            { id => 199, data => '5' },
            { id => 40, data => '9' },    
            { id => 100, data => { name => 'author', value => 'Admin' } }
    ],    
    id => 55    
  },
  id => 1  
};
print join(', ', ids($data));

这里有一个简单的递归解决方案。很容易看出这里发生了什么

# There is a faster version of `uniq` provided by List::MoreUtils on CPAN.
sub uniq {
    my %seen;
    grep !$seen{$_}++, @_;
}

sub ids {
    my $val = shift;
    my $ref = ref $val;
    my @r;

    if ($ref eq 'HASH')
    {
        @r = map ids($_), grep ref, values(%$val);
        push @r, $val->{id} if exists $val->{id};
    }

    elsif ($ref eq 'ARRAY')
    {
        @r = map ids($_), grep ref, @$val;
    }

    sort { $a <=> $b } uniq(@r);
}

$data不包含有效的Perl数据结构,例如,元素的值是多少?也许多个排序不会提高效率。@mpapec-您的答案也是如此。我说的是在递归函数中使用排序。@mpapec,我也是。您有相互递归的函数。我猜是偶然的。
# There is a faster version of `uniq` provided by List::MoreUtils on CPAN.
sub uniq {
    my %seen;
    grep !$seen{$_}++, @_;
}

sub ids {
    my $val = shift;
    my $ref = ref $val;
    my @r;

    if ($ref eq 'HASH')
    {
        @r = map ids($_), grep ref, values(%$val);
        push @r, $val->{id} if exists $val->{id};
    }

    elsif ($ref eq 'ARRAY')
    {
        @r = map ids($_), grep ref, @$val;
    }

    sort { $a <=> $b } uniq(@r);
}
# There is a faster version of `uniq` provided by List::MoreUtils on CPAN.
sub uniq {
    my %seen;
    grep !$seen{$_}++, @_;
}

sub ids {
    my @r;
    while (@_) {
        my $val = shift;
        my $ref = ref($val);

        if ($ref eq 'HASH')
        {
            push @r, $val->{id} if exists $val->{id};
            push @_, grep ref, values %$val;
        }

        elsif ($ref eq 'ARRAY')
        {
            push @_, grep ref, @$val;
        }
    }

    sort { $a <=> $b } uniq(@r);
}