Search code examples
listmappingrakusequential

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.


Solution

  • 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)