Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simple way to do mapping of group of sequential list elements

Normal mapping applies a function to a list element and produces an element of the resultant list. E.g., if list is (1, 2, 3,) and maps the square function, you get a new list (1, 4, 9,).

Is there a way to map a group of sequential elements of a list? For instance, if the list is <8 2 7 2 6 9 4 9 6 1> and I want to calculate the sum of every 2 elements of the list to make <10 9 9 8 15 13 13 15 7>?

I can certainly write a routine to traverse the list. But I am looking for an easier way, like the reduction operator or like the gather/take.

like image 659
lisprogtor Avatar asked Dec 27 '17 08:12

lisprogtor


2 Answers

You can use the .rotor method to partition a list into overlapping sublists:

say <8 2 7 2 6 9 4 9 6 1>.rotor(2 => -1);

# Output:
# ((8 2) (2 7) (7 2) (2 6) (6 9) (9 4) (4 9) (9 6) (6 1))

The 2 => -1 is a Pair argument which signifies to the method that it should generate the sublists by going "two forward, one back" at each step.

Then you can simply use .map to apply your operation (e.g. sum) to each sublist:

say <8 2 7 2 6 9 4 9 6 1>.rotor(2 => -1).map(*.sum);

# Output:
# (10 9 9 8 15 13 13 15 7)
like image 103
smls Avatar answered Nov 15 '22 13:11

smls


The functional programming way to do this is to reference the list twice, offset one version by an element, and zip them together. This gives you all the tuples of subsequent elements.

my @l := <a b c d e f>;
say @l Z @l[1..*]; # output: ((a b) (b c) (c d) (d e) (e f))

If you don't want to create a temporary variable to hold the list, use given (and use do given if you need the statement to return a value):

given <8 2 7 2 6 9 4 9 6 1> {
  say ($_ Z $_[1..*]).map: -> [$a, $b] { $a+$b };
}

If you're using a function that takes two parameters, you may want to flatten the list after zipping and let map take two elements at a time:

given <8 2 7 2 6 9 4 9 6 1> {
  say ($_ Z $_[1..*]).flat.map(&infix:<+>);
}
like image 20
piojo Avatar answered Nov 15 '22 14:11

piojo