我有以下用例,我在同一个集合中多次迭代,每次在该集合中找到不同的项目。
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
}
有更好的方法吗?一次迭代?
答案 0 :(得分:1)
如果它是一个大型集合,折叠成地图意味着你只构建感兴趣的集合。
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))
然后
scala> val milk = res5("milk")
milk: C = C(milk)
scala> val bread = res5.get("bread")
bread: Option[C] = None
原始groupBy
解决方案已被删除,因为有人评论说它做了额外的工作,但实际上它是一个简单的表达式,如果创建中间列表列表就可以了。
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
或
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)))
答案 1 :(得分:0)
groupBy
会这样做:
val byType = list.groupBy(_.type).withDefaultValue(Nil)
val milk = byType(Milk).headOption
val other = byType(Other)
等...