Reputation: 4428
I have the following recursive function to remove items from a list (zooResidents: List[(String, Int)]) that are contained in another list (pets: List[String]). It works, but is very slow. What is the Scala way of doing this?
val pets = List("cat", "dog")
val zooResidents = List(("cat", 4), ("lion", 2), ("tiger", 3), ("dog", 2)
def removePets(zooResidents: List[(String, Int)], pets: List[String]): List[(String, Int)] = {
if (pets.isEmpty) zooResidents
else removePets(zooResidents.filterNot(_._1.contains(pets.head)), pets.tail)
}
removePets(zooResidents, pets) //> res2: List[(String, Int)] = List((lion,2), (tiger,3))
Upvotes: 3
Views: 1096
Reputation: 1099
val zooResidents = List(("cat", 4), ("lion", 2), ("tiger", 3), ("dog", 2)
val pets = List("cat", "dog")
Try this one-liner:
zooResidents.filter(x=>pets.toSet.contains(x._1)==false)
scala> zooResidents.filter(x=>pets.toSet.contains(x._1)==false)
res167: List[(String, Int)] = List((lion,2), (tiger,3))
pets changed to be a Set for performance.
This takes zooResidents List and checks for existence of each string in pets also and returns only those elements of zooResidents which are not in pets the ==false
will do this.
Upvotes: 1
Reputation: 8663
This is what I would call scala way
@ zooResidents filterNot { case (resident, _) => pets contains resident }
res6: List[(String, Int)] = List(("lion", 2), ("tiger", 3))
For better performance, pets
should be a Set
.
filterNot
takes only those elements that do not fulfill the predicate, i.e. those for which the given function returns false
. So we want to take all those elements for which pets
does not contain first element of the tuple.
You can use pattern matching instead of regular function to destructure tuple as I did this
{ case (resident, _) => pets contains resident }
this is equvalent to
(residentTuple => pets.contains(residentTuple._1))
Upvotes: 2
Reputation: 23329
Note that List#contains
is linear as it has to scan the entire list, I would recommend you using a data-structure with constant-time lookup like Set
val petSet = pets.toSet
val filter = zooResidents.filterNot(element => petSet.contains(element._1))
Upvotes: 5