0

I have three arrays that need to be stored together for future use. Each array is related to each other, and every array element per position is meant to be matched together. The arrays elements orders will always be correct, but beyond that, there is no easy way to discern the correct order once lost.

How can I combine these arrays together without losing their original order?

I am assuming that an array of hashes is the best way to go, but, please let me know if I'm wrong in that assumption.

Example Arrays:

my @numbers = (5,2,7,32,9);
my @letters = qw(z b t t c);
my @words   = qw(tiny book lawn very dance);

Example end result.

my @combined_arrays = (
       {
           'number' => '5',
           'letter' => 'z',
           'word'   => 'tiny',
       },
       {
           'number' => '2',
           'letter' => 'b',
           'word'   => 'book',
       },
       {
           'number' => '7',
           'letter' => 't',
           'word'   => 'lawn',
       },
       {
           'number' => '32',
           'letter' => 't',
           'word'   => 'very',
       },
       {
           'number' => '9',
           'letter' => 'c',
           'word'   => 'dance',
       },
);
8
  • 2
    Why not use an array of arrays: my @combined_arrays = (\@numbers, \@letters, \@words ) ? or my @combined_arrays = ([@numbers], [@letters], [@words] ) if you need to make a copy... Commented Jul 2, 2018 at 19:47
  • 1
    Other than the shown hashes it may also be an array-of-arrays as ([5,'z','tiny'], ...), if you want to group them by position. For how to create either see this recent page (near duplicate). Commented Jul 2, 2018 at 19:58
  • I should have mentioned I wanted to pour this into a db at some point. I was thinking that the array of hashes would be easier to iterate over. Commented Jul 2, 2018 at 20:09
  • @user: There seems to be no reason to use hashes. If you know that the items are always in the order number, letter, word then there is no confusion. I also recommend an array of arrays for simplicity and economy of space. (Using hashes, you would be storing many many copies of the three strings 'number', 'letter', and 'word') Commented Jul 2, 2018 at 20:14
  • 1
    @user: Sure, but that answer shows how to build an array of hashes, which as I've said is unnecessary, very wasteful, and long-winded to process. I'm trying to address your "trouble breaking out of [the loop] and not creating duplicates". You should learn how to do this properly sooner rather than later, and not just accept the first example that works. Commented Jul 2, 2018 at 22:51

2 Answers 2

4

I would do it like this

my @combined_arrays = map { "number" => $numbers[$_] , "letter" => $letters[$_] , "word" => $words[$_] } , 0..@letters-1;
Sign up to request clarification or add additional context in comments.

3 Comments

I very much, made this more complicated than it needed to be. Thanks, that does it. :)
NP, map is really handy for one liners where you need to iterate though a list. You could have also done this using a for loop and push each entry onto the array. However, this would take an extra line ;-)
@letters-1 == $#letters :)
3

I realise you've already accepted an answer, but I thought I'd just throw out a more concise option that relies on some modules.

I'm using zip (aka mesh, from either List::SomeUtils or List::MoreUtils) and zip_by (from List::UtilsBy), but I'm importing both of them via List::AllUtils.

use strict;
use warnings;
use List::AllUtils qw( zip zip_by );

my @numbers = (5,2,7,32,9);
my @letters = qw(z b t t c);
my @words   = qw(tiny book lawn very dance);
my @keys    = qw(number letter word);

my @combined = zip_by { +{ zip @keys, @_ } } \@numbers, \@letters, \@words;

It's potentially more readable, but only if you're familiar with what zip and zip_by do. At the very least, it fits inside 80 characters.

Update I originally had \%{{ zip @keys, @_ }} inside the zip_by. This was to force it to interpret my curlies as a hash-ref. Then I remembered that +{} is a prettier way to disambiguate.

1 Comment

Thanks, this is helpful.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.