slayedbylucifer
slayedbylucifer

Reputation: 23512

rewrite map code without using map

I am working on a perl script which calls VMware vSphere perl API. I was facing few problems and while googling, I found a solution which seems to work for me. However, one of the important piece of the code is written with map. Credit goes to the VMware community member who wrote it. Here is the code:

$datastore_map = map { $_->{'mo_ref'}->{'value'} => $_  } @{$datastore_views || [ ]};

I am not able to understand what above line is doing.

So, Could you help me to convert above line into a foreach loop or something similar. Believing in TMTOWTDI, there has to be another way to write same logic.

I tried to learn the map function a lot of times but it always bounces off my head. Hence I want to implement above logic without using the map function.

EDIT:

After reading the answers, I think the it should be %datastore_map and not $datastore_map. Because the next line of the code is $datastore = $datastore_map->{$moref->{'value'}};

It has to be a typo.

I will accept the answer when stacoverflow allows me to. Thanks for the quick repsonces. I spend almost an hour trying to understand it and failed at it.

Thanks.

EDIT:

Thanks @nickisfat, @choroba and @ikegami for the responses. All the answers are correct but I can accept only one. So I will go with the one which was posted first in the chronological order. Thanks again for the answers.

Upvotes: 0

Views: 101

Answers (3)

ikegami
ikegami

Reputation: 386216

map BLOCK LIST

is very similar to

do {
   my @list;
   for (LIST) {
      push @list, do BLOCK;
   }
   @list
};

The code you posted makes no sense. Either the LHS of the assignment was actually a hash, or there's a set of curlies missing. Let's say your code is actually

my $datastore_map = {
    map { $_->{'mo_ref'}->{'value'} => $_ }
     @{ $datastore_views || [ ] }
};

Before we start, let's rewrite that to the following to make things a bit simpler.

my %datastore_map =
    map { $_->{'mo_ref'}->{'value'} => $_ }
     @{ $datastore_views || [ ] };

my $datastore_map = \%datastore_map;

So that means what you have is equivalent to

my %datastore_map = do {
   my @list;
   for (@{ $datastore_views || [ ] }) {
      push @list, do { $_->{'mo_ref'}->{'value'} => $_ };
   }
   @list
};      

my $datastore_map = \%datastore_map;

And we can simplify that to

my %datastore_map;
for (@{ $datastore_views || [ ] }) {
   $datastore_map{ $_->{'mo_ref'}->{'value'} } = $_;
}      

my $datastore_map = \%datastore_map;

or

my %datastore_map;
if ($datastore_views) {
   for (@$datastore_views) {
      $datastore_map{ $_->{'mo_ref'}->{'value'} } = $_;
   }
}      

my $datastore_map = \%datastore_map;

Upvotes: 4

beresfordt
beresfordt

Reputation: 5222

$datastore_views is an array containing hashes, the code creates a hash of those hashes ($datastore_map) keyed on the contents of {'mo_ref'}->{'value'}.

In foreach:

foreach my $item( @$datastore_views ){
    $datastore_map->{ $item->{'mo_ref'}->{'value'} } = $item;
}

edit:

or at least thats what it would be doing if the original code was:

%$datastore_map = map { $_->{'mo_ref'}->{'value'} => $_  } @{$datastore_views || [ ]};

Upvotes: 1

choroba
choroba

Reputation: 241948

Are you sure you want to assing the result to a scalar?

If not, just use the following:

my %datastore_map;
for my $view (@$datastore_views) {
    $datastore_map{$view->{mo_ref}{value}} = $view;
}

If yes, you want to get the number of views times 2. So, use simply

$datastore_map = 2 * @$datastore_views;

But, in such a case, the name of the variable is badly chosen.

Upvotes: 1

Related Questions