Reputation: 3503
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
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
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
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
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
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
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