Edit elements of MutableList

Viewed 715

I am trying to edit the elements located within a MutableList but they seem to be val types. Here is what I have tried:

for(note in item.notes.toMutableSet()) {
    note = note.trim()
}

I keep getting an error like: val cannot be reassigned. Any suggestions on how to edit the element directly from the list and having this change reflected in the list as well.

3 Answers

Why not create a new set, like this?

    val newNotes = item.notes.map{ it.trim() }.toSet()

The note variable within the for expression is immutable

For mutable list of immutable elements you may do the following for in place mutation:

val list = mutableListOf(" 111 ", " 123 ")

for ((index, value) in list.withIndex()) {
    list[index] = value.trim()
}

If the object already has methods to mutate it's own state it's enough to iterate through it because you're not modifying the collection per-se

Given the following object:

data class Thing(var thing: String) {
    fun trimThing() {
        thing = thing.trim()
    }
}

// somewhere else

fun trimAll(things: List<Thing>) {
    // No need to edit the list because the mutation happens on the item level
    things.forEach { thing -> thing.trimThing() }
}

However if you want to mutate a list itself you need to transform the list (or any collection) into a MutableCollection. Here's an example with lists

Kotlin already provides utility functions that do the very thing just for you:


fun trimStrings(strs: List<String>): List<String> {
    val mutStrs = strs.toMutableList()
    for(i in 0 until mutStrs.size) {
        mutStrs[i] = mutStrs[i].trim()
    }
    return mutStrs.toList()
}

Symmetric calls exist for other collection types such as Set -> MutableSet

Even though this is quite nice, we're still dealing with mutability which is something discouraged in Kotlin since it is a common cause of bugs.

As @Twistleton has suggested it's way more kotlinish (idiomatic Kotlin) to just create a new List out of the first you had by doing

fun trimNotes(item: YourType) {
    return item.notes.map{ it.trim() }
}
Related