Letfar
Letfar

Reputation: 3503

Divide list into parts

Is there a simple way to divide list into parts (maybe some lambda) in Kotlin?

For example:

[1, 2, 3, 4, 5, 6] => [[1, 2], [3, 4], [5, 6]]

Upvotes: 47

Views: 36686

Answers (6)

Blundell
Blundell

Reputation: 76458

If you want to divide a list into N parts. (and not divide a list into parts of size N) You can still use the chunked answer:

https://stackoverflow.com/a/48400664/413127

Only, first you need to find your chunk size.

val parts = 2
val list = listOf(10, 2, 3, 4, 5, 6)
val remainder = list.size % 2 // 1 or 0
val chunkSize = (list.size / parts) + remainder
val chunked = list.chunked(chunkSize)
println(chunked)

This prints out

[[10, 2, 3], [4, 5, 6]]

or when

val parts = 3

This prints out

[[10, 2], [3, 4], [5, 6]]

Interesting answer in Python here: Splitting a list into N parts of approximately equal length

Upvotes: 1

Ernest Zamelczyk
Ernest Zamelczyk

Reputation: 2817

Nice way of dividing list is by the use of function partition. Unlike groupBy it doesn't divide list by keys but rather by predicate which gives out Pair<List, List> as a result.

Here's an example:

val (favorited, rest) = posts.partition { post ->
    post.isFavorited()
}
favoritedList.addAll(favorited)
postsList.addAll(rest)

Upvotes: 14

gil.fernandes
gil.fernandes

Reputation: 14591

The better answer is actually the one authored by VasyaFromRussia.

If you use groupBy, you will have to add and index and then post-process extracting the value from an IndexedValue object.

If you use chunked, you simply need to write:

val list = listOf(10, 2, 3, 4, 5, 6)
val chunked = list.chunked(2)
println(chunked)

This prints out:

[[10, 2], [3, 4], [5, 6]]

Upvotes: 33

VasyaFromRussia
VasyaFromRussia

Reputation: 1972

Since Kotlin 1.2 you can use Iterable<T>.chunked(size: Int): List<List<T>> function from stdlib (https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/chunked.html).

Upvotes: 90

miensol
miensol

Reputation: 41608

Given the list: val list = listOf(1, 2, 3, 4, 5, 6) you can use groupBy:

list.groupBy { (it + 1) / 2 }.map { it.value }

Or if your values are not numbers you can first assign an index to them:

list.withIndex()
    .groupBy { it.index / 2 }
    .map { it.value.map { it.value } }

Or if you'd like to save some allocations you can go a bit more manual way with foldIndexed:

list.foldIndexed(ArrayList<ArrayList<Int>>(list.size / 2)) { index, acc, item ->
    if (index % 2 == 0) {
        acc.add(ArrayList(2))
    }
    acc.last().add(item)
    acc
}

Upvotes: 38

EdH
EdH

Reputation: 5003

The API says there is a GroupBy function, which should do what you want.

https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/group-by.html

Or use sublist and break it up yourself

https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/sub-list.html

Upvotes: 2

Related Questions