https://kotlinlang.org logo
#getting-started
Title
# getting-started
n

Nat Strangerweather

03/17/2022, 7:39 PM
With this line of code, I have a situation where if there is one "A" in
letterList.value
all the "A"s in
boardLetterList
are removed. Is there a way of getting only one "A" filtered out if I only have one in my letterList?
Copy code
val difference = boardLetterList.filterNot{ letterList.value!!.contains(it) }
y

Youssef Shoaib [MOD]

03/17/2022, 7:51 PM
MutableCollection.remove()
specifies:
Removes a single instance of the specified element from this collection, if it is present.
and so:
Copy code
val difference = buildList(boardLetterList.size) {
    addAll(boardLetterList)
    for (letter in letterList.value!!){
        remove(letter)
    }
}
n

Nat Strangerweather

03/17/2022, 7:53 PM
Thanks, this works nicely! 😊
e

ephemient

03/17/2022, 9:29 PM
if you want to do this more efficiently, you can use a multiset/counting map
e.g.
Copy code
fun <T> Iterable<T>.removeAllOnce(elements: Iterable<T>): List<T> {
    val removeCounts = elements.groupingBy { it }.eachCountTo(mutableMapOf())
    return this.filter { element ->
        val count = removeCounts[element] ?: return@filter true
        if (count > 0) {
            removeCounts[element] = count - 1
            false
        } else true
    }
}
👍 2
y

Youssef Shoaib [MOD]

03/18/2022, 9:09 AM
Is that that much efficient though? groupingBy is iterating once over the removal elements (O(n) for speed) and adding them all into a map (O(n) for space) and then you're iterating over the original elements (O(m) for speed) and adding only the valid elements (O(m - n) for space) Oh right,
remove
has to iterate over the whole list to find the element to remove. So yes, OP, the removeAllOnce solution with the multiset is significantly faster!
🙌 1
e

ephemient

03/19/2022, 1:48 AM
yep, you're comparing O(m + n) < O(m * n). stdlib's
Iterable.removeAll
does something similar but without counting
2 Views