简体   繁体   中英

Better way to iterate on a collection and find multiple values instead of 1

I have the following use case, in which I am iterating multiple times on the same collection, and every time I find a different item in that collection.

class Foo(policyToData: Map[String, MyClass]){
   val milk: Option[MyClass] = policyToData.values.find(_.`type` == Milk)
   val meat: Option[MyClass] = policyToData.values.find(_.`type` == Meat)
   val bread: Option[MyClass] = policyToData.values.find(_.`type` == Bread)
   val other: List[MyClass] = policyToData.values.filter(_.`type` == Other).toList
}

Is there a better way to do it? with one iteration?

If it's a large collection, folding into a map means you only build the collection of interest.

scala> case class C(name: String)
defined class C

scala> val cs = List(C("milk"),C("eggs"),C("meat"))
cs: List[C] = List(C(milk), C(eggs), C(meat))

scala> cs.foldLeft(Map.empty[String,C]) {
     | case (m, c @ C("milk" | "meat")) if !m.contains(c.name) => m + (c.name -> c)
     | case (m, _) => m }
res5: scala.collection.immutable.Map[String,C] = Map(milk -> C(milk), meat -> C(meat))

then

scala> val milk = res5("milk")
milk: C = C(milk)

scala> val bread = res5.get("bread")
bread: Option[C] = None

The original groupBy solution was deleted because someone commented that it does extra work, but in fact it's a straightforward expression, if creating the intermediate Map of Lists is OK.

scala> cs.groupBy(_.name)
res0: scala.collection.immutable.Map[String,List[C]] = Map(meat -> List(C(meat)), eggs -> List(C(eggs)), milk -> List(C(milk)))

scala> res0.get("milk").map(_.head)
res1: Option[C] = Some(C(milk))

scala> res0.get("bread").map(_.head)
res2: Option[C] = None

or

scala> cs.filter { case C("milk" | "meat") => true case _ => false }.groupBy(_.name)
res4: scala.collection.immutable.Map[String,List[C]] = Map(meat -> List(C(meat)), milk -> List(C(milk)))

groupBy will do it:

   val byType = list.groupBy(_.type).withDefaultValue(Nil)
   val milk = byType(Milk).headOption
   val other = byType(Other)

Etc ...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM