Data looks like this
class Person (
var id:Int,
var name:String
)
class Option (
var level:Int
)
val p1 = Person(1, "A")
val p2 = Person(2, "B")
val opt1 = Option((0..1000).random())
val opt2 = Option((0..1000).random())
val opt3 = Option((0..1000).random())
val opt4 = Option((0..1000).random())
val arr = listOf(
listOf(p1,p2,opt1),
listOf(p1,p2,opt2),
listOf(p1,p2,opt3),
listOf(p2,p1,opt4)
)
I would like to get "A" and "B" as unique values of name.
It's easy if collection looks like this:
val simple = listOf(p1,p2,p2,p1).distinctBy{it.name}
simple.forEach {
println(it.name)
}
CodePudding user response:
The following should work as expected:
fun main() {
val p1 = Person(1, "A")
val p2 = Person(2, "B")
val opt1 = Option((0..1000).random())
val opt2 = Option((0..1000).random())
val opt3 = Option((0..1000).random())
val opt4 = Option((0..1000).random())
val arr = listOf(
listOf(p1,p2,opt1),
listOf(p1,p2,opt2),
listOf(p1,p2,opt3),
listOf(p2,p1,opt4)
)
val distinctNames = arr.flatten().mapNotNull {
when(it) {
is Person -> it.name
else -> null
}
}.distinct()
println(distinctNames)
}
class Person (
var id:Int,
var name:String
)
class Option (
var level:Int
)
However, I would advise you to replace the nested Lists if possible so that you can avoid the when
block while mapping. If possible I would suggest Triple
class instead as follows:
fun main() {
val p1 = Person(1, "A")
val p2 = Person(2, "B")
val opt1 = Option((0..1000).random())
val opt2 = Option((0..1000).random())
val opt3 = Option((0..1000).random())
val opt4 = Option((0..1000).random())
val arr = listOf(
Triple(p1,p2,opt1),
Triple(p1,p2,opt2),
Triple(p1,p2,opt3),
Triple(p2,p1,opt4)
)
val distinctNames = arr.flatMap { listOf(it.first.name, it.second.name) }
.distinct()
println(distinctNames)
}
Another possibility if you want/need to keep the nested Lists would be the following (thanks @gidds for the hint):
fun main() {
val p1 = Person(1, "A")
val p2 = Person(2, "B")
val opt1 = Option((0..1000).random())
val opt2 = Option((0..1000).random())
val opt3 = Option((0..1000).random())
val opt4 = Option((0..1000).random())
val arr = listOf(
listOf(p1,p2,opt1),
listOf(p1,p2,opt2),
listOf(p1,p2,opt3),
listOf(p2,p1,opt4)
)
val distinctNames = arr.flatten().mapNotNull { (it as? Person)?.name }
.distinct()
println(distinctNames)
}
CodePudding user response:
Another option can be to create a custom class to represent your inner lists.
class PersonOption(
val person1: Person,
val person2: Person,
val option: Option
)
val arr = listOf(
PersonOption(p1, p2, opt1),
PersonOption(p1, p2, opt2),
PersonOption(p1, p2, opt3),
PersonOption(p2, p1, opt4)
)
val names = arr.flatMap { listOf(it.person1.name, it.person2.name) }.distinct()
println(names)