2016-03-26 6 views
0

Ich habe den folgenden Anwendungsfall, in dem ich mehrere Male auf der gleichen Sammlung wiederhole, und jedes Mal finde ich ein anderes Element in dieser Sammlung.Bessere Möglichkeit, auf eine Sammlung zu iterieren und mehrere Werte anstelle von 1 zu finden

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 
} 

Gibt es einen besseren Weg, es zu tun? mit einer Iteration?

Antwort

1

Wenn es sich um eine große Sammlung handelt, bedeutet das Zusammenfalten zu einer Karte, dass Sie nur die gewünschte Sammlung erstellen.

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)) 

dann

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

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

Die ursprüngliche groupBy Lösung gelöscht wurde, weil jemand bemerkte, dass es zusätzliche Arbeit tut, aber es ist ein einfacher Ausdruck, wenn die Erstellung der Zwischen Karte von Listen in der Tat ist 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 

oder

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))) 
0

groupBy wird es tun:

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

Etc ...

+0

@somsnytt "für die erste Reichweite"? Wdym? – Dima

+0

Ich bin mir nicht sicher, wie 'falten' hier die Leistung in irgendeiner Weise unterstützt. – Dima

+0

@ som-snytt niemand kopiert die gesamte Sammlung, es sind nur Referenzen, die kopiert werden. Wenn Sie denken, dass _das_ eine große Sache ist, sollten Sie nicht Scala mit dem ganzen "unveränderlichen/Kopie-auf-schreiben" -Paradigma verwenden, um damit zu beginnen. Ich meine, was glaubst du, was dein 'm + (c.name -> c)' tut? – Dima

Verwandte Themen