2014-01-24 70 views
2

在斯卡拉2.10.3,我看到這個問題。如何解決斯卡拉2.10.x弄平問題

Welcome to Scala version 2.10.3 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_25). 
Type in expressions to have them evaluated. 
Type :help for more information. 


scala> val list = List(1, 2, List(5, 6)) 
list: List[Any] = List(1, 2, List(5, 6)) 

scala> list.flatten 
<console>:9: error: No implicit view available from Any => scala.collection.GenTraversableOnce[B]. 
      list.flatten 
       ^

如何解決此問題?

我目前的解決方法是定義我自己的扁平函數。

def flat(list: List[Any]): List[Any] = list flatten { 
    case i: List[Any] => flat(i) 
    case e => List(e) 
} 

scala> flat(list) 
res2: List[Any] = List(1, 2, 5, 6) 

回答

6

您的解決方案有效。但是,一般來說,有一個List[Any]似乎是一個不受歡迎的情況。應該避免使用Any,因爲它確實可以繞過類型檢查器爲您所做的好事。

更好的解決辦法可能是使用專門設計的類層次結構:

sealed trait Tree { 
    def flatten: List[Int] 
} 

case class Node(children: List[Tree]) extends Tree { 
    def flatten = children.flatMap(_.flatten) 
} 

case class Leaf(n: Int) extends Tree { 
    def flatten = List(n) 
} 

然後:

val t = Node(List(Leaf(1), Leaf(2), Node(List(Leaf(5), Leaf(6))))) 
t.flatten // List(1, 2, 5, 6) 

而且你還可以這樣做:

def flat(t: Tree): List[Int] = t match { 
    case Node(children) => children.flatMap(c => flat(c)) 
    case Leaf(n) => List(n) 
} 

所以:

flat(t) // List(1, 2, 5, 6) 
+0

所以,我想,我有寫我自己的房子。斯卡拉的拼合不再適用 – Billz

+0

斯卡拉拼合的工作很好;然而,無法平整一個List [Any],因爲類型檢查器不知道Any是否可以遍歷。 – dhg

+0

僅僅因爲Scala可以讓你省略類型聲明,並不意味着它是一種動態語言。你應該抵制像Python那樣編寫Scala代碼的衝動。 – geoffliu

2

你的問題是,沒有隱式方式來做你想要的扁平化:(Any => List[Any])

你可以養活你flat功能的修改版本爲flatten達到你想要的效果:

val x = List(1, 2, List(3, 4)) 

def flat2(any: Any): List[Any] = 
    any match { 
    case i: List[_] => i 
    case _ => List(any) 
    } 

x.flatten(flat2) 
8

嗯,這不是一個問題與Scala 2.10.3但而每一個版本,因爲2.8.0時引入flatten。而且它是完全表現良好:

flatten基本上沒有:

這個集合遍歷的集合轉換成這些穿越集合的元素形成的集合 。

所以總之你的類型A需要有一個函數A => GenTraversableOnce它可以幫助你遍歷它們。你的情況:

scala> val x = List(1, 2, List(3, 4)) 
x: List[Any] = List(1, 2, List(3, 4)) 

xList[Any]型的,它是不可能有Any類型爲任何人,每個人都通用的功能都會有自己的定義。你可以改爲做的是: (將工作多個嵌套列表也):

def flatten(ls: List[Any]): List[Any] = ls flatMap { 
    case i: List[_] => flatten(i) 
    case e => List(e) 
} 

val k = List(1, List(2, 3), List(List(List(List(4)), List(5)), List(6, 7)), 8) 
flatten(k) 

它打印List[Any] = List(1, 2, 3, 4, 5, 6, 7, 8)