2016-03-26 22 views
0

yerine birden çok değer bulmanın daha iyi bir yolu Aşağıda, aynı koleksiyonda birden çok kez yinelemeyi ve bu koleksiyonda farklı bir öğe bulduğum her seferde kullanıyorum.Koleksiyonda yineleme ve 1

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 
} 

Bunu yapmanın daha iyi bir yolu var mı? tek iterasyon ile?

cevap

1

Eğer büyük bir koleksiyonsa, bir haritaya katlamak sadece ilgi koleksiyonunu oluşturuyor demektir.

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

sonra

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

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

orijinal groupBy çözüm birisi ekstra çalışma yaptığı yorum yaptığı silinmez ancak Listelerinin ara Harita oluşturma yolunda olup olmadığını aslında, basit bir deyim oldu.

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 

veya

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 yapacak:

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

Vb ...

+0

@somsnytt "ilk Reach for"? Wdym? – Dima

+0

Performansın herhangi bir önemli şekilde nasıl katlanacağına emin değilim. – Dima

+0

@ som-snytt kimse koleksiyonun tamamını kopyalamaz, sadece kopyalanan referanslar. _that_ büyük bir anlaşma olduğunu düşünüyorsanız, başlamak için "immutable/copy on-write" paradigması ile scala kullanmamalısınız. Demek istediğim, senin "m + (c.name -> c)" nin ne yaptığını düşünüyorsun? – Dima