2015-12-21 106 views
1

我有簡單的層次斯卡拉列表覆蓋到cortage

class A 
case class B extends A 
case class C extends A 
case class D extends A 

而且需要功能

def f(list: List[A]) : (List[B], List[C], List[D]) = ??? 

我可以收集B,C,d在muttable名單,但我想它在fucntional風格寫

回答

0

對於我來說,在這種情況下使用帶有列表的累加器是相當理想的:

 case class Cortage(bs: List[B], cs: List[C], ds: List[D]) { 
    def asCortage = (bs, cs, ds) 
    } 

    def f(list: List[A], acc: Cortage = Cortage(List(), List(), List())): (List[B], List[C], List[D]) = 
    list match { 
     case x :: t => f(t, 
     x match { 
     case x:B => acc.copy(bs = x :: acc.bs) 
     case x:C => acc.copy(cs = x :: acc.cs) 
     case x:D => acc.copy(ds = x :: acc.ds) 
     }) 
     case Nil => acc.asCortage 
    } 
1

什麼可能比舊的Foldable功能更多stdscalaz好友的庫實例。

import scalaz.syntax.foldable._ 
import scalaz.std.tuple._ 
import scalaz.std.list._ 

def f(list: List[A]) = list foldMap { 
    case b: B => (List(b), Nil, Nil) 
    case c: C => (Nil, List(c), Nil) 
    case d: D => (Nil, Nil, List(d)) 
} 

然而要注意長名單注意到追加要素相當不錯,所以多一點點有效的實現可能是

import scalaz.syntax.foldable._ 
import scalaz.std.tuple._ 
import scalaz.std.vector._ 
import scalaz.std.list._ 
import scalaz.syntax.std.tuple._ 

def f(list: List[A]) = list foldMap { 
    case b: B => (Vector(b), Vector(), Vector()) 
    case c: C => (Vector(), Vector(c), Vector()) 
    case d: D => (Vector(), Vector(), Vector(d)) 
} mapElements (_.toList, _.toList, _.toList) 
+0

非常好的解決方案 – punksta

4

另一個變化

list.foldLeft((List.empty[B], List.empty[C],List.empty[D])) { case ((bs, cs, ds), a) => 
    a match { 
     case x: B => (x :: bs, cs, ds) 
     case x: C => (bs, x :: cs, ds) 
     case x: D => (bs, cs, x :: ds) 
    } 
    } 
0

因爲我不能發表評論答案,我提供了我的解決方案,其中 保留了訂單幷包括A的情況。

def f(xs: List[A]): (List[B], List[C], List[D]) = { 
    @tailrec 
    def group(xs: List[A], bs: List[B], cs: List[C], ds: List[D]): (List[B], List[C], List[D]) = xs match { 
    case Nil => (bs.reverse, cs.reverse, ds.reverse) 
    case (b: B) :: t => group(t, b :: bs, cs, ds) 
    case (c: C) :: t => group(t, bs, c :: cs, ds) 
    case (d: D) :: t => group(t, bs, cs, d :: ds) 
    case _ :: t => group(t, bs, cs, ds) 
    } 

    group(xs, List(), List(), List()) 
}