Issue
I have these code segments. I want to find the optimal solution and if it's possible some explanation why my 1st piece of code is broken. I have struggled with adding elements to the existing Array<>, without minimal external stuff. I tried with +=' '.plus()
, and.plusElement()
, and the only solution I found to work is by coping the current array to MutableList and then adding an element to it. After that, I convert it again to Array and return the right type Array<>. I am sure that there is a more elegant way, but I can't brainstorm it.
Question 2: I also tried to shorten the code with with()
, let{}
run{}
, etc. to make program.description.data.options as it.
or this.
instead of creation of new var clone
Thank you in advance :)
I have some nested data classes for Serialization in Kotlin
*FavouriteProgramCommandString
have property val description: FavouriteProgram
->
FavouriteProgram
have val data: FavouriteProgramDetails
-> FavouriteProgramDetails
have var options: Array<FavouriteProgramOptions>,
*
data class FavouriteProgramDetails(
@SerializedName(value = "key", alternate = ["featureKey"])
val key: String,
@SerializedName("options")
var options: Array<FavouriteProgramOptions>,
)
Broken code:
@JvmStatic
fun getProgramDescriptionOfFavouritesWithDelayOption(
program: FavouriteProgramCommandString,
key: String,
delayDuration: Double = 0.0,
): FavouriteProgram {
with(program.description.data.options) {
val nodeOption =
firstOrNull { it.key == key }
if (nodeOption != null) {
this[this.indexOf(nodeOption)].value = delayDuration
} else {
this.plus(FavouriteProgramOptions(key, delayDuration)) // DONT'WORK
}
}
return program.description // Absolutly the same array is returned.
}
Working code:
@JvmStatic
fun getProgramDescriptionOfFavouritesWithDelayOptio2n(
program: FavouriteProgramCommandString,
key: String,
delayDuration: Double = 0.0,
): FavouriteProgram {
val clone = program.description.data.options.toMutableList()
val nodeOption =
clone.firstOrNull { it.key == key }
if (nodeOption != null) {
val index = clone.indexOf(nodeOption)
clone[index].value = delayDuration
} else {
clone.add(FavouriteProgramOptions(key, delayDuration)) // It's working.
}
program.description.data.options = clone.toTypedArray()
return program.description // Return what is expected.
}
Solution
Elements cannot be added to or removed from an array. What you can do is create new arrays, with new elements, and this is what methods like toTypedArray
and plus
do. You need to assign this newly created array back to program.description.data.options
, like you did in your working attempt:
program.description.data.options = clone.toTypedArray()
^^^
you assigned it here
Scope functions won't help you if you don't assign the newly created array!
program.description.data.options = with(program.description.data.options) {
val nodeIndex = indexOfFirst { it.key == key }
if (nodeIndex != -1) {
this.also { this[nodeIndex].value = delayDuration }
} else {
this + FavouriteProgramOptions(key, delayDuration)
}
}
Notice the assignment at the very beginning. with
returns either this
, with some changes, or a copy of this
, but with one new element added. I've replaced plus
with the operator form, which is more idiomatic, and avoided going through the array twice by using indexOfFirst
.
In my opinion, it would be better for program.description.data.options
to be a MutableMap
instead. Then it would be easier to do this kind of operation. It'd be a simple getOrPut
:
program.description.data.options.getOrPut(key) { FavouriteProgramOptions(key, delayDuration) }.value = delayDuration
Even using a MutableList
instead would avoid making copies of the entire array each time you do this.
Answered By - Sweeper
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.