Perl: Can you use more than two arrays in the map function?

Viewed 131

I've been learning Perl as of late, and ran into an interesting problem. How would I go about using two arrays in map like so?

use warnings;
use strict;
use Data::Dumper;

my $names->{name} = ['Bill', 'Smith'];
my $cars->{model} = ['Honda', 'Toyota'];

my $obj = {
    'Students' => [
    map {
        'Name' => $_, 
        'Model' => $_ 
        }, @{$names->{name}}, @{$cars->{model}}
    ]
};

print Dumper $obj;

This will print, it's producing two too many objects than I would like.

$VAR1 = {
          'Students' => [
                          {
                            'Model' => 'Bill',
                            'Name' => 'Bill'
                          },
                          {
                            'Model' => 'Smith',
                            'Name' => 'Smith'
                          },
                          {
                            'Model' => 'Honda',
                            'Name' => 'Honda'
                          },
                          {
                            'Model' => 'Toyota',
                            'Name' => 'Toyota'
                          }
                        ]
        };

What I'd like to do is have map work in a way that it'll produce these results

$VAR1 = {
          'Students' => [
                          {
                            'Model' => 'Honda',
                            'Name' => 'Bill'
                          },
                          {
                            'Model' => 'Toyota',
                            'Name' => 'Smith'
                          }
                        ]
        };
3 Answers
use warnings;
use strict;

use Data::Dumper;

my $names->{name} = [ qw(Bill Smith) ];
my $cars->{model} = [ qw(Honda Toyota) ];

my $obj = { 
    Students => [
        map {
            { Name => $names->{name}[$_], Model => $cars->{model}[$_] }
        } 
        0 .. $#{$names->{name}}
    ]   
};      
    
print Dumper $obj;

The body of the map uses both arrays so you only need to supply indices to it.

For this both arrayrefs must be of same length and items to be paired at same indices.

The syntax $#$arrayref is for the last index in the $arrayref, and since here we have to also dereference first there's an extra pair of {}.


What you have dereferences both arrayrefs, to build a single flat list for the map, producing

my $obj = {
    'Students' => [
    map {
        'Name' => $_, 
        'Model' => $_ 
        }, qw(Bill Smith Honda Toyota);
    ]
};

First, this makes no sense:

my $names->{name} = ['Bill', 'Smith'];
my $cars->{model} = ['Honda', 'Toyota'];

I'll use

my @names  = ( 'Bill', 'Smith' );
my @models = ( 'Honda', 'Toyota' );

We could iterate over the indexes.

map { +{ Name => $names[$_], Model => $cars[$_] } }
   0..$#names

Alternatively, we could enlist zip.

use List::Util qw( zip );

map { +{ Name => $_->[0], Model => $_->[1] } }
   zip \@names, \@models

This is probably better written as a while loop:

my @names  = qw( Bill  Smith  );
my @models = qw( Honda Toyota );
my @students;
push @students, { 'name' => shift @names, 'model' => shift @models } while @names;
Related