Home > other >  Why can't I use removeAll on a list of objects?
Why can't I use removeAll on a list of objects?

Time:05-20

I am trying to create an app that let's you type in what you want to eat and drink. It calculates all of that and then when you press the print button, I want it to count how often each item's in the list and give it back like this:

"9x Juice /n 5x Steaks /n 4x Salads"

The drinks and foods are objects in the new class Edibles:

class Edibles(val name: String, val price: Double):Serializable {

}

I track all of the objects in the MutableList order and can access the different members of the list and their attributes, but when I try to removeAll duplicates in my list, android studio complains and I don't know how to fix it.

My try to calculate how many members are in the list order:

var totalOrder = ""
    for(i in order){
        var number = order.count {it == order[0]}
        totalOrder = totalOrder   "$number"   "x"   order[0].name   "\n"
        order.removeAll(order[0])
    }

The problem as far as I saw so far is, that Edibles doesn't have the interface Collection and when I try to implement that, it wants me to override a bunch of functions where I don't know what to do with it...

If anyone has an explanation or even a fix or an idea on how to do it differently, I would be very grateful

CodePudding user response:

removeAll is meant to take a list or a predicate, not a single element. If you convert your element to a predicate checking for equality, it will remove all elements equal to that one.

order.removeAll { it == order[0] }

However, you'll also need to remember rule number one of iteration: Never delete while iterating. So what you really want to do is accumulate all of the "deletion" candidates into a list and then delete them after-the-fact.

In fact, what you're doing here can be done without mutating the list at all, using a built-in list combinator called groupBy.

var totalOrder = ""
for (entry in order.groupBy { it }) {
  val item = entry.key
  val count = entry.value.size
  totalOrder  = "${count}x${item.name}\n"
}

CodePudding user response:

You're not allowed to mutate a collection while iterating it in a for loop anyway. One way to remove duplicates would be to create a temporary MutableSet and compare each item to it in a removeAll operation. removeAll takes a lambda predicate that is called on each item and the Boolean you return from the predicate. When you call add on a MutableSet, it returns a Boolean to tell you if the item already was in the set, so you can remove duplicates with the following.

Assuming you just want to compare names of items to determine if they are duplicates, you can create a MutableSet<String>.

with (mutableSetOf<String>()) {
    order.removeAll { add(it.name) }
}
  • Related