http://www.perlmonks.org?node_id=1029827

anirudh.agarwal has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks, I would like to convert a array of hash ref to hash and check a value in it. This is how it goes. The following code gets the array reference in $ams_hosts

my $ams_hosts = $request->get_config()->get_ams_hosts($domain);
The following code
print STDERR Dumper @{$ams_hosts};
prints this
$VAR1 = { 'domainId' => '1', 'deviceIp' => '172.16.133.56', 'deviceType' => 3, 'deviceName' => 'AMS' }; $VAR2 = { 'domainId' => '1', 'deviceIp' => '172.16.133.57', 'deviceType' => 3, 'deviceName' => 'ams_57' };
Now i would like to check if a scalar variable, say $ams_ip=172.16.133.52, does not exist in the above hash assign undef to $ams_ip. I thought of assigning the array to hash with (key,value) as (deviceIp,<its correspponding ip address like 172.16.133.56> ) I tried the following snippet
my %ams_ips_hash = map {$_->{'deviceIp'}++} @{$ams_hosts}; $ams_ip = "" if !exists $ams_ips_hash{ $ams_ip};
but it doesnt work. Please let me know what I am doing wrong and what would make it right. As I am new to perl, I would be obliged to learn from perl monks like you. Your help is highly appreciated. Thanks in advance :) .

Replies are listed 'Best First'.
Re: Converting array of hash references to hash
by hdb (Monsignor) on Apr 22, 2013 at 09:30 UTC

    In map you need to return pairs to fill your hash:

    my %ams_ips_hash = map { $_->{'deviceIp'} => 1 } @{$ams_hosts};

      Personally I'd...

      my %ams_ips_hash = map { $_->{'deviceIp'} => $_ } @{$ams_hosts};
      package Cow { use Moo; has name => (is => 'lazy', default => sub { 'Mooington' }) } say Cow->new->name
        Thanks for your reply. This one stores (key,value) as (IP, entire hash). This is again not what I want.
      What actually happens in your case is, the value of deviceIp, say, 172.16.133.56changes to 172.16. Is it because that perl is taking it as an integer?

        I do not understand. If I run:

        use strict; use warnings; use Data::Dumper; my $ams_hosts = [ { 'domainId' => '1', 'deviceIp' => '172.16.133.56', 'deviceType' => 3, 'deviceName' => 'AMS' }, { 'domainId' => '1', 'deviceIp' => '172.16.133.57', 'deviceType' => 3, 'deviceName' => 'ams_57' } ]; my %ams_ips_hash = map { $_->{'deviceIp'} => 1 } @{$ams_hosts}; print Dumper( \%ams_ips_hash );

        I get

        $VAR1 = { '172.16.133.56' => 1, '172.16.133.57' => 1 };

        Can you clarify what you mean please?

Re: Converting array of hash references to hash
by hdb (Monsignor) on Apr 22, 2013 at 09:40 UTC

    You can also answer your question w/o creating a hash:

    $ams_ip = "" unless grep { $ams_ip eq $_->{'deviceIp'} } @{$ams_hosts} +;

    but this would be computationally more expensive if you need to perform this query many times.

      This one definitely works. Thanks. This query is executed only once per request in my case. I hope in that case even if  @{$ams_hosts} has a large data, it wont be expensive. :) Thanks again
      I verified that use of any instead of grep increases the performance.
        > I verified that use of any instead of grep increases the performance.

        sure, but List::MoreUtils is not core...

        lanx@nc10-ubuntu:~$ corelist List::MoreUtils List::MoreUtils was not in CORE (or so I think)

        ... thats why it's easier to show working code w/o dependencies.

        With List::MoreUtils present any is for sure the better choice!

        Cheers Rolf

        ( addicted to the Perl Programming Language)

      When I check the above statement using Perl Critic, it finds the following violation. "grep" used in boolean context. I see this strange.
        I then found that grep would search for the rest of the array even if a match is found in the first record itself. I believe any should be used. Let me try the following $ams_ip = "" unless any { $ams_ip eq $_->{'deviceIp'} } @{$ams_hosts}; Please let me know if I am wrong. Thanks :)
Re: Converting array of hash references to hash
by Anonymous Monk on Apr 22, 2013 at 09:16 UTC
    Why do you have ++ in  $_->{'deviceIp'}++?
      I feel it is a similar way of giving $_->{'deviceIp'}=>1. But I am not sure.
Re: Converting array of hash references to hash
by rpnoble419 (Pilgrim) on Apr 22, 2013 at 16:54 UTC

    Why do the conversion in the first place. If the data is consistent, write your program to loop through the array. It might be helpful to look at this tread Map Vs Foreach. I'm not against using map, but if the list is very long you may run into other problems.

    UPDATE:

    you may want to check out this module to see if does what you want Hash-MostUtils