Reputation: 172
I'm converting a one dimensional array into a multidimensional array. See the below codefor what I am doing. I'm still learning perl and so want to have an improvement on my code.
My Question: Can I do the conversion in one line?
I think Perl is able to do so. When writing a subroutine it's possible to assign:
my ($one, $two, $three) = @_;
My code:
#!/usr/bin/perl -w
use strict;
use warnings;
use Data::Dumper;
my @oneDim = (
'COL', 'EUR', 'Fruit', 'apple',
'HZP', 'USD', 'Fruit', 'banana',
'HKG', 'USD', 'Food', 'burger',
'IML', 'USD', 'IT', 'keyboard');
# (@fourDim[0],@fourDim[1],@fourDim[2],@fourDim[3]) = @oneDim;
sub main() {
my @fourDim = ([],[],[],[]);
for (my $i = 0; 4 * $i + 3 < scalar(@oneDim); ++$i)
{
push @{$fourDim[0]}, $oneDim[$i * 4 + 0];
push @{$fourDim[1]}, $oneDim[$i * 4 + 1];
push @{$fourDim[2]}, $oneDim[$i * 4 + 2];
push @{$fourDim[3]}, $oneDim[$i * 4 + 3];
}
print Dumper @fourDim;
}
main();
And this is the result:
$VAR1 = [
'COL',
'HZP',
'HKG',
'IML'
];
$VAR2 = [
'EUR',
'USD',
'USD',
'USD'
];
$VAR3 = [
'Fruit',
'Fruit',
'Food',
'IT'
];
$VAR4 = [
'apple',
'banana',
'burger',
'keyboard'
];
I found the reverse conversion here: https://stackoverflow.com/a/8611430/2764334
But I could not find an elegant way to convert a one dimensional array into a multidimensional. In my case I know that there is always the same order (code, currency, type, product)
Upvotes: 1
Views: 50
Reputation: 98398
Almost one line, but easy to understand:
use List::MoreUtils 'part';
my $i = 0;
my @fourDim = part { $i++ / 4 } @oneDim;
As usual, reduce can do it in one line but is harder to understand:
use List::Util 'reduce';
my $fourDim = reduce { push @{ $a->[ @$a && @{$a->[-1]} < 4 ? -1 : @$a ] }, $b; $a } [], @oneDim;
though those are the ways that would work just as well on lists of unknown size; given an array @oneDim, you can just do:
my @fourDim = map [ @oneDim[$_*4..$_*4+3] ], 0..@oneDim/4-1;
Upvotes: 3
Reputation: 98028
Splice may help:
my @oneDim = (
'COL', 'EUR', 'Fruit', 'apple',
'HZP', 'USD', 'Fruit', 'banana',
'HKG', 'USD', 'Food', 'burger',
'IML', 'USD', 'IT', 'keyboard');
my @fourDim;
my $k = @oneDim / 4;
push @fourDim, [ splice @oneDim, 0, $k ] while @oneDim;
print join(", ", @$_), "\n" for @fourDim;
this gives:
COL, EUR, Fruit, apple
HZP, USD, Fruit, banana
HKG, USD, Food, burger
IML, USD, IT, keyboard
Upvotes: 1