Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Recursivly flatten a multidimensional array

What's the shortest way to flat a multidimensional array?
Here's some examples of what I mean:

# 2D array
my @a = [1,2],[3,4];
say @a».Slip.flat;                # prints (1 2 3 4)
# 3D array
my @b = [[1,2],[3,4]],[[5,6],[7,8]];
say @b».Slip».flat».Slip.flat;    # prints (1 2 3 4 5 6 7 8)
                                  # but needs to know how many dimensions
                                  # there are to flatten

Is it possible to recursively flatten an array of arrays such as @b without writing a sub which recursively descends into it or having any knowledge of the number of its dimensions?
I'm asking this because I trust the compiler (now or in a future implementation) to be able to optimize more an operator-based solution than a sub.

like image 879
Fernando Santagata Avatar asked Oct 13 '18 08:10

Fernando Santagata


1 Answers

Not sure if there's a more compact way, but

say do gather @b.deepmap(*.take);

should do it.

If you do not care for the order of the flattened result,

say do gather @b>>.take;

might also be an option, though it 'feels' wrong to me to (ab)use hyper operators for side effects...


Until proper handling of HyperWhatever slicing suggested by raiph arrives in core, you could add your own sugar @b[**] covering this specific use case via

multi sub postcircumfix:<[ ]>(\SELF, HyperWhatever:D $, *% where !*) {
    gather SELF.deepmap(*.take);
}
like image 161
Christoph Avatar answered Sep 30 '22 02:09

Christoph