How to flatten List of Lists in Kotlin?
Asked Answered
F

6

35

I have a list of objects of class AA that contain a date and a list of objects of class BB:

data class AA(
    val date: LocalDate,
    val bb: List<BB>
)

@Parcelize
data class BB(
    val x: Int,
    val y: String,
    val z: String
) : Parcelable

I want to create a single List (flatten List<AA>) that will look like this:

 listOf(
    date obj
    BB obj
    BB obj
    date obj
    BB obj
    date obj
    BB obj
    BB obj 
    BB obj)

Instead of:

 listOf(
    date obj, listOf(BB obj, BB obj)
    date obj, listOf(BB obj)
    date obj, listOf(BB obj, BB obj, BB obj))

I tried using flatMap, but I only manage to flatten one part - BB.
How to crate a list with date and BB items?

Flapjack answered 5/8, 2019 at 10:38 Comment(5)
Possible duplicate of Divide elements on groups in RecyclerView or Grouping Recyclerview items ,say by dateSwayne
@Hardik Chauhan - My question was how to flatten the list. The RecyclerView is what it will be used for and is not relevant (I removed it). Anyway the answer there is about grouping. I need to represent existing objects. So it's not a duplicate question!Flapjack
what is item in the flattened list? It does not seem to appear in the List<AA>Rafaelrafaela
@Rafaelrafaela - Basically if my List<AA> looks like that: listOf((date1,listOf(2,a,b), (date2,listOf((3,v,d),(5,c,j))) etc. Then I want a list: listOf(date1,(2,a,b),date2,(3,v,d),(5,c,j))Flapjack
I edited to make it more clearFlapjack
R
22

As answered by @DYS you can and should use flatten to flatten a list. My answer covers how to achieve the special case stated in the question.

You can do it this way:

val a = listOf(
    AA(LocalDate.now(), listOf(BB(1, "1", "1")))
)
val flattened = a.flatMap { aa -> mutableListOf<Any>(aa.date).also { it.addAll(aa.bb) }}

see complete example

Basically you use flatMap, create a MutableList<Any> with the date and then addAll items of BB in the also block. Probably there is a more elegant way to do it but this one came to me first.

Simply using flatten does not work here, because AA does not implement iterable.

Rafaelrafaela answered 5/8, 2019 at 11:11 Comment(0)
P
47

The simplest one I know of is the extension flatten() function to Iterable. Since List is a subclass of the latter, it is applicable.

https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/flatten.html

val deepList = listOf(listOf(1), listOf(2, 3), listOf(4, 5, 6))
println(deepList.flatten()) // [1, 2, 3, 4, 5, 6]
Precipitin answered 20/9, 2019 at 11:19 Comment(4)
You can also do this: listOf(1) + listOf(2,3) + listOf(4,5,6) (which is shorthand for: listOf(1).plus(listOf(2,3)).plus(listOf(4,5,6))) to get the same results.Plastic
As you can see OP has different types for nested lists. How is this even related to the question and why people keep upvoting this?Kling
@Kling I think the emphasis of this question is more about flattening list of lists than about list of lists of different types, as suggested by the title of the question.Precipitin
@Precipitin Well if you answer questions by only title, then nothing to say. Content of the question is there for a reason right?! Imagine how ambiguous answers you would get if people only read the title and answered accordinglyKling
R
22

As answered by @DYS you can and should use flatten to flatten a list. My answer covers how to achieve the special case stated in the question.

You can do it this way:

val a = listOf(
    AA(LocalDate.now(), listOf(BB(1, "1", "1")))
)
val flattened = a.flatMap { aa -> mutableListOf<Any>(aa.date).also { it.addAll(aa.bb) }}

see complete example

Basically you use flatMap, create a MutableList<Any> with the date and then addAll items of BB in the also block. Probably there is a more elegant way to do it but this one came to me first.

Simply using flatten does not work here, because AA does not implement iterable.

Rafaelrafaela answered 5/8, 2019 at 11:11 Comment(0)
K
0

You can simply try this:

fun flattenNestedList(list: List<List<Any>>?) = list?.flatten() ?: emptyList()
Karolkarola answered 5/5, 2021 at 21:16 Comment(1)
As you can see OP has different types for nested listsKling
O
0

The best way I've found to flatten lists:

val flatList = listOf<String>("A", "B", *listOf("C", "D").toTypedArray())
Overcash answered 2/12, 2022 at 9:5 Comment(0)
F
0

Some year after but here some simple examples:

With lists of lists

val array = listOf(listOf("a", "b"), listOf("c", "b"))
.flatten().toTypedArray()

With arrays of arrays

val array = arrayOf(arrayOf("a", "b"), arrayOf("c", "b"))
.flatten().toTypedArray()

With lists of arrays

val array = listOf(arrayOf("a", "b"), arrayOf("c", "b"))
.flatMap { it.toList() }.toTypedArray()

hope to help someone.

Fouts answered 29/3, 2023 at 0:32 Comment(0)
G
0

Iterable.flatMap can be used to flatten structures:

data class Data(
    val list: List<Int>,
)
fun main() {
    val deepList: List<Data> = listOf(Data(listOf(1)), Data(listOf(2, 3)), Data(listOf(4, 5, 6)))
    val flatMap = deepList.flatMap { data: Data -> data.list }
    println(flatMap) // [1, 2, 3, 4, 5, 6]
}

it's pretty much similar to the Iterable.flatten() answer

Gazetteer answered 18/6, 2024 at 23:8 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.