I've the below Input and the expected output.
Input : [undef,[0,1],2]
Expected Output : [0,1,2]
Code I've written:
use Data::Dumper;
my $input=[undef,[0,1],2];
my @arr=@{$input};
@arr = grep {defined} @arr;
my @arrnew;
foreach my $value (@arr){
if (ref $value eq 'ARRAY') {
push @arrnew,@{$value};
} else {
push @arrnew,$value;
}
}
print Dumper(@arrnew);
Question: Although, this gives me the correct output, would like to know if any simpler way of doing this in perl.
CodePudding user response:
You can roll it all into a single expression using map
and grep
.
use strict;
use warnings;
my $foo = [undef,[0,1],2];
my @bar = map { ref eq 'ARRAY' ? @$_ : $_ } grep defined, @$foo;
The map
acts like your foreach
loop and produces a new list on the way out, which gets assigned to a new array @bar
. The grep
you had already used, but I've changed it to use expression syntax rather than block syntax.
Note this only works for one level of depths.
CodePudding user response:
For deeper structures, you can use a recursive subroutine:
#!/usr/bin/perl
use warnings;
use strict;
sub flatten {
my ($thing) = @_;
return unless defined $thing;
return $thing unless ref $thing;
return map flatten($_), @$thing;
}
my $input = [undef, [0, 1], 2, [[[3]]]];
my $output = [flatten($input)];
use Test::More tests => 1;
is_deeply $output, [0, 1, 2, 3];