Search code examples
c++functional-programminggroupingrange-v3list-processing

ranges::views::group_by-like function applying predicate to consecutive elements?


In the following small example I was trying to group elements by the difference between consecutive elements being 1. As the output shows, however, group_by's predicate is evaluated between the current element and the first element of the group being processed.

#include <iostream>
#include <range/v3/view/group_by.hpp>

int main() {
    using ranges::views::group_by;
    std::vector<int> v{1,2,3,6,7,8,9,12,14,15};
    for (auto i : v | group_by([](auto x2,auto x1){ return x2 - x1 == 1; })) {
        std::cout << i << '\n';
    }
}

Does Range-v3 offer a way to evaluate the predicate between consecutive elements of the group?

I once asked the same question for Haskell, and it turned out a namesake function is on Hackage.


Solution

  • group_by has been deprecated in favor of chunk_by, which does exactly what you want:

    Given a source range and a binary predicate, return a range of ranges where each range contains contiguous elements from the source range such that the following condition holds: for each element in the range apart from the first, when that element and the previous element are passed to the binary predicate, the result is true. In essence, views::chunk_by groups contiguous elements together with a binary predicate.

    using ranges::views::chunk_by;
    std::vector<int> v{1,2,3,6,7,8,9,12,14,15};
    for (auto i : v | chunk_by([](auto l, auto r){ return r - l == 1; })) {
        std::cout << i << '\n';
    }
    

    Prints

    [1,2,3]
    [6,7,8,9]
    [12]
    [14,15]