Create List<Object> from List<List<Object>> in kotlin - kotlin

I have List<List> and I want to create List where I have all cars from List<List>. There is any way in Kotlin to create that (using map or something)? I don't want to create new list and add items in loops

val listOfLists: List<List<Int>> = listOf(listOf(1, 2, 3), listOf(4, 5))
One way would be to use flatten function. This function just flattens the inner lists
val flatten: List<Int> = listOfLists.flatten() //[1, 2, 3, 4, 5]
But if you need to do some transformation as well as flattening the list then you can do it with flatMap():
val flatMap: List<Int> = listOfLists.flatMap { it.map { it*2 } } //[2, 4, 6, 8, 10]

tl;dr List.flatten()
Let's say your List<List<Car>> is called carLists, then you can simply call val cars: List<Car> = carLists.flatten() if you want to have a single list containing all the cars from the list of lists of cars.
Code only:
val carLists: List<List<Car>> = … // created or received
val cars = carLists.flatten()

Related

Kotlin, is it possible to access the pair of a map?

Is it possible to access the whole Pair of a map, not only the key or a value?
Let's say we have a map
map = mapOf(Pair("Example1", 1), Pair("Example2", 2), Pair("Example3",
3))
I would like to access the second pair and put it into a variable, something like I would do with a list:
val ex2 = map[1] #this would result with {"Example2", 2}
And then i would be able to access the pair's key/value like:
ex2.key / ex2.value
More specifically, I would like to use this in my function to return a specific pair of the map.
Not sure if this would help
val mapString = mutableMapOf(1 to "Person", 2 to "Animal")
val (id, creature) = 1 to mapString.getValue(1)
Log.e("MapPair", "$id, $creature")
prints
1, Person
or if you're iterating through the entire map
mapString.forEach {
val (id, creature) = it.key to it.value
Log.e("MapPair", "$id : $creature")
}
prints
1 : Person
2 : Animal
or using Pair
val key = 1
val pair = Pair(key, mapString.getValue(key))
Log.e("MapPair", "$pair")
prints
(1, Person)
or if you're iterating through the entire map using Pair
mapString.forEach {
val pair = Pair(it.key, it.value)
Log.e("MapPair", "$pair")
}
prints
(1, Person)
(2, Animal)
Update: For iterating through the map you can also go with Destructuring Declarations
val mapString = mutableMapOf(1 to "Person", 2 to "Animal")
for ((key, value) in mapString) {
Log.e("MapComponents", "$key, $value")
}
From your comment, it seems like you want to fetch the key corresponding to a given value.
val map = mapOf("Chicken" to 20, "Egg" to 10, "Bread" to 5)
val valueToFind = 20
val key = map.toList().find { it.second == valueToFind }?.first
println(key)
Output:
Chicken
If the value doesn't exist, it will give null.

Sum Mutable Map values inside a list of objects kotlin

I have a data class in Kotlin like this:
data class Activity(
var id: String? = "",
var prize: MutableMap<String?, Int?>? = null
)
And a list of this object:
var myList = listOf(Activity("A", prize={day_5=70, day_4=70}),
Activity("B", prize={day_5=40, day_4=80}))
The desired result is:
Activity("A", prize={total=140}),
Activity("B", prize={total=120})
So basically I want to sum the values of the prize map inside of each object.
I think that has something to do with transformation but I'm new to Kotlin and I couldn't find any resources over the internet, or maybe they were to complicated.
This algorithm is easy, just iterating through all the maps and replace elements with the sum:
val myList = listOf(
Activity("A", hashMapOf("day_5" to 70, "day_4" to 70)),
Activity("B", hashMapOf("day_5" to 40, "day_4" to 80)),
)
for (i in myList) {
val total = i.prize.values.sum()
i.prize.clear()
i.prize["total"] = total
}

Create list of lists in kotlin?

How do I create a list of lists?
I have a mutable list of ints:
val rsrpList = mutableListOf<Int>()
Now I am trying to create a list of lists, like this:
val rsrpList = mutableListOf<Int>()
val rsrqList = mutableListOf<Int>()
val levelList = mutableListOf<Int>()
val listoflists = List<List<Int>>
listoflists.add(rsrpList)
listoflists.add(rsrqList)
listoflists.add(levelList)
but I know this is wrong, because I'm adding a list one at a time, instead of a list of lists. How would I do this?
You can do this with the Kotlin Standard Library. Both List and MutableList can be created to a specific size (3 in this case) and specify a lambda that will initialize each value.
val listOfList = MutableList(3) { mutableListOf<Int>() }
Or:
val listOfList = List(3) { mutableListOf<Int>() }
Update: To initialize a List with precreated lists:
val listOfList = listOf(list1, list2, list3)
Or in your specific case:
val listOfList = listOf(rsrpList, rsrqList, levelList)
And in both cases you can replace listOf with mutableListOf if you want a mutable list as the main type.
Your example is fine (you have an empty list, you're adding lists to that list, you end up with a list of lists!) but if you're trying to avoid mutability by declaring everything at once:
val listOfLists = listOf(rsrpList, rsrqList, levelList)
and you can declare those lists at the same time if you want
val listOfLists = listOf(
listOf(1, 2, 3),
listOf(9, 8, 7),
listOf(7, 7, 7)
)
or you can use mutableListOf if you need any of them to be mutable! The formatting there isn't necessary, I just think it looks clearer how they're nested

How to map a list by chunks in kotlin

I often end up with data sources like (pseudo code below, not any specific syntax, it is just to illustrate):
list = {
"XLabel",
"XDescription",
"YLabel",
"YDescription",
"ZLabel",
"ZDescription"
}
desired output is:
list = {
MyClass("XLabel", "XDescription"),
MyClass("YLabel", "YDescription"),
MyClass("ZLabel", "ZDescription")
}
Is there anything more clean than to do a fold(), and fold it into a new list? I've also rejected doing something weird like list.partition().zip()
I basically want a more powerfull map that would work like mapChunks( it1, it2 -> MyClass(it1, it2)) where the chunking is part of the function so it gets easy and nice. (My example has the list in chunks of two, but 3 is also a prevalent use case.)
Does this function exist? Or what is the most idiomatic way to do this?
You can use the chunked function, and then map over the result. The syntax gets very close to what you wanted if you destructure the lambda-argument:
list.chunked(2)
.map { (it1, it2) -> MyClass(it1, it2) }
// Or use _it_ directly: .map { MyClass(it[0], it[1]) }
I think the windowed method should do what you want.
lst.windowed(size = 2, step = 2, partialWindows = false) { innerList -> MyClass(innerList[0], innerList[1]) }
You can also use chunked but it calls windowed under the hood. But with chunked you can get lists that have fewer elements than you were expecting
EDIT to answer #android developer's question about getting the indexes of the list
val lst = listOf(7, 8, 9, 10, 11, 12, 13, 14, 15, 16)
val windowedList = lst.mapIndexed { index, it -> index to it }
.windowed(size = 2, step = 2, partialWindows = false) {
it[0].first
}
println(windowedList)
Would output
[0, 2, 4, 6, 8]
To add to the existing answers, you can use chunked function with the transform lambda passed as its second argument:
list.chunked(2) { (label, description) -> MyClass(label, description) }
This way is more efficient because the temporary list of two elements is reused across all chunks.
You can create an extension function, for example mapChunks, and reuse it:
fun List<String>.mapChunks(): List<MyClass> {
return chunked(2).map { MyClass(it[0], it[1]) }
}
val list1 = listOf(
"XLabel",
"XDescription",
"YLabel",
"YDescription",
"ZLabel",
"ZDescription"
)
val result1 = list1.mapChunks()
val list2 = listOf(
"XLabel1",
"XDescription1",
"YLabel1",
"YDescription1",
"ZLabel1",
"ZDescription1"
)
val result2 = list2.mapChunks()
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/chunked.html
Chunked returns a sub list of the size you specify
This is the API call you want
considering your list is in pairs of 2 you can do this
list.chunked(2) //List<List<String>>
.map{MyClass(it[0], it[1]} //list<MyClass>

How do I create a map from 2 arrays?

I have a string array and an integer array. How do I create a map using the first as keys and the second as values?
val keys = arrayOf("butter", "milk", "apples")
val values = arrayOf(5, 10, 42)
val map: Map<String, Int> = ???
How to convert List to Map in Kotlin? doesn't solve this problem; I have 2 arrays and want a single map.
You can zip together the arrays to get a list of pairs (List<Pair<String, Int>>), and then use toMap to get your map.
Like this:
val keys = arrayOf("butter", "milk", "apples")
val values = arrayOf(5, 10, 42)
val map: Map<String, Int> =
keys.zip(values) // Gives you [("butter", 5), ("milk", 10), ("apples", 42)]
.toMap() // This is an extension function on Iterable<Pair<K, V>>
According to kotlin
Constructing Collections
-> creating a short-living Pair object, is not recommended only if performance isn't critical and to quote: "To avoid excessive memory usage, use alternative ways. For example, you can create a mutable map and populate it using the write operations. The apply() function can help to keep the initialization fluent here."
since I'm not much of an expert I run on to these code and maybe this should work better?:
val numbersMap = mutableMapOf<String,Int>()
.apply{ for (i in 1.. 5) this["key$i"] = i }
println(numbersMap)
//result = {key1=1, key2=2, key3=3, key4=4}
or to adjust it to question above - something like this:
val keys = arrayOf("butter", "milk", "apples")
val values = arrayOf(5, 10, 42)
val mapNumber = mutableMapOf<String, Int>()
.apply { for (i in keys.indices) this[keys[i]] = values[i] }
println(mapNumber)