Perl loop thru nested blessed hashref elements

856 Views Asked by At

I have a perl data structure similar to the following:

$VAR1 = bless( {
                 'admin' => '0',
                 'groups_list' => [
                                           bless( {
                                                    'name' => undef,
                                                    'groupid' => 'canedit',
                                                    'description' => 'Can Edit Articles'
                                                  }, 'group_entry' ),
                                           bless( {
                                                    'name' => undef,
                                                    'groupid' => 'webuser',
                                                    'description' => 'Can Access Content'
                                                  }, 'group_entry' ),
                                         ],
                 'trusted' => '1',
               }, 'user_info' );

I am looking for a way to loop thru all the groups in 'groups_list' and check if we have 'webuser' groupid in it. Any help is appreciated.

Also, kindly let me know if this can be done without using a loop.. something like searching for the string 'groupid' => 'webuser' ..

3

There are 3 best solutions below

2
On BEST ANSWER

blessing reference only add arbitrary type description to it and doesn't change working with it in any other way, unless you use overload, so exactly same loop as with unblessed references will work:

foreach my $group (@{$VAR1->{groups_list}}) {
   if ($group->{groupid} eq 'webuser') {
      # do stuff and break out
   }
}

You can also replace loop with grep if you only need inner hashes with data without their indices in array:

my @webusers = grep { $_->{groupid} eq 'webuser' } @{$VAR1->{groups_list}};

This will search entire list though. Use first from List::Util to only find first match.

0
On

This will loop through and find it:

foreach (@{$VAR1->{'groups_list'}})
{
    if ($_->{'groupid'} eq 'webuser')
    {
        print "found webuser.";
    }   
}

You can't really do this without looping, because your task inherently involves looking at each element.

0
On

Since the groups have been blessed into a package, you should probably not be checking for the existence of hash keys directly, instead add a method to the group_entry class like this (something similar may already exist):

{
  package group_entry;
  sub get_groupid {
     my $self = shift;
     $self->{groupid}
  }
}

and since your data is also blessed into the user_info package, create a method on user_info to filter the groups by groupid (your user_info class may already have something like this):

{
  package user_info;
  sub get_groups_list {
     my $self = shift;
     return @{ $self->{groups_list} }
  }
  sub filter_groups_by_groupid {
    my $self = shift;
    my ($filter_groupid) = @_;
    return grep { $_->get_groupid eq $filter_groupid } $self->get_groups_list
  }
}

and in your code, do something like:

my @webusers = $data->filter_groups_by_groupid( 'webuser' );