Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Group sequences of values

I'm wondering if there's in any nifty way to use the new Stream APIs to "group" sequences of values.

e.g. split a series of integers, into groups of integers where each group is an ascending number sequence:

IntStream seq = IntStream.of(1, 2, 3, -1, -1, 1, 2, 1, 2);
IntFunction next = i -> i + 1;

// DESIRED OUTPUT: [[1,2,3], [-1], [-1], [1,2], [1,2]]
like image 778
rednoah Avatar asked Feb 05 '16 21:02

rednoah


People also ask

What is GROUP BY value?

The GROUP BY statement groups rows that have the same values into summary rows, like "find the number of customers in each country". The GROUP BY statement is often used with aggregate functions ( COUNT() , MAX() , MIN() , SUM() , AVG() ) to group the result-set by one or more columns.

Where or GROUP BY which comes first?

In the query, GROUP BY clause is placed after the WHERE clause. In the query, GROUP BY clause is placed before ORDER BY clause if used any.

How do you find the first value of each group?

groupby. nth() function is used to get the value corresponding the nth row for each group. To get the first value in a group, pass 0 as an argument to the nth() function.


1 Answers

Unfortunately, the Stream API is not very well suited to tackle problems that involve dependant operations on the Stream element, like this one.

However, you can use the StreamEx library for this:

public static void main(String[] args) {
    IntStream seq = IntStream.of(1, 2, 3, -1, -1, 1, 2, 1, 2);
    IntUnaryOperator next = i -> i + 1;

    List<List<Integer>> result = 
        IntStreamEx.of(seq).boxed().groupRuns((i1, i2) -> next.applyAsInt(i1) == i2).toList();

    System.out.println(result); // prints "[[1, 2, 3], [-1], [-1], [1, 2], [1, 2]]"
}

This groups into a List all consecutive integers where the second one is equal to the next function applied to the first one. Finally, this Stream is collected into a List.

like image 185
Tunaki Avatar answered Oct 01 '22 10:10

Tunaki