0

How to chunk a list in specific value?

Ex: split where current value is 5

val x = listOf(1,2,3,4,5,2,3,1,5,4,1,5)

convert x to this:

x => [[1,2,3,4,5],[2,3,1,5],[4,1,5]]
kaMChy
  • 441
  • 5
  • 9
  • Do you want to split the list into chunks with exactly 5 items, or do you want to split it such that the last item in each chunk is `5`?  (Unfortunately, your example is one of the rare cases where both give the same result.) – gidds Feb 04 '21 at 23:37
  • Second case, I want to chunk at specific "5" value – kaMChy Feb 06 '21 at 02:57

1 Answers1

1

Surprisingly, there isn't a method to do this in the standard library.  But it's not hard to write one yourself, e.g.:

/**
 * Splits a collection into sublists, following each occurrence of the given separator.
 */
fun <T> Collection<T>.splitAfter(separator: T): List<List<T>> {
    val result = mutableListOf<MutableList<T>>()
    
    var newSublist = true
    for (item in this) {
        if (newSublist)
            result += mutableListOf<T>()
        result.last() += item
        newSublist = (item == separator)
    }
    
    return result
}

That does as required:

val x = listOf(1, 2, 3, 4, 5, 2, 3, 1, 5, 4, 1, 5)
println(x.splitAfter(5)) // prints [[1, 2, 3, 4, 5], [2, 3, 1, 5], [4, 1, 5]]

It also handles all the corner cases: an empty list, consecutive separators, and zero or more leading and/or trailing separators, e.g.:

val x = listOf(5, 5, 4, 5, 5, 2)
println(x.splitAfter(5)) // prints [[5], [5], [4, 5], [5], [2]]

(It would be a good idea to include unit tests covering all such cases, of course.)

gidds
  • 16,558
  • 2
  • 19
  • 26