With this line of code, I have a situation where i...
# getting-started
n
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
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
Thanks, this works nicely! 😊
e
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
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
yep, you're comparing O(m + n) < O(m * n). stdlib's
Iterable.removeAll
does something similar but without counting