2012-10-24 107 views
11

我想寫一個列表的功能。斯卡拉flatten列表

object Flat { 
    def flatten[T](list: List[T]): List[T] = list match { 
    case Nil => Nil 
    case head :: Nil => List(head) 
    case head :: tail => (head match { 
     case l: List[T] => flatten(l) 
     case i => List(i) 
    }) ::: flatten(tail) 
    } 
} 

object Main { 
    def main(args: Array[String]) = { 
    println(Flat.flatten(List(List(1, 1), 2, List(3, List(5, 8))))) 
    } 
} 

我不知道爲什麼它不工作,則返回List(1, 1, 2, List(3, List(5, 8)))但它應該是List(1, 1, 2, 3, 5, 8)

你能給我一個提示嗎?

+0

這是一個有趣的練習。對於實際的代碼,當然,在List中有一個'flatten'方法。 – AshleyF

+0

這在這種情況下不起作用。這裏的列表是一個'List [Any]',所以你必須從Any => TraversableOnce [_]定義一個隱式轉換來調用flatten。這一定是可能的,但我懷疑它比這個函數更簡單。 – rjsvaljean

+0

看看編譯器的錯誤和警告:他們會給出一些很大的線索 –

回答

9

通過刪除線4

case head :: Nil => List(head) 

你會得到正確的答案。

想想測試用例

List(List(List(1))) 

隨着4號線最後一個元素列表將不會被處理

26

你不需要巢您匹配語句。取而代之的是這樣的匹配:

def flatten(xs: List[Any]): List[Any] = xs match { 
    case Nil => Nil 
    case (head: List[_]) :: tail => flatten(head) ++ flatten(tail) 
    case head :: tail => head :: flatten(tail) 
    } 
+0

非常優雅的解決方案,謝謝分享! – Ashalynd

15

我的,相當於SDJMcHattie的解決方案。

def flatten(xs: List[Any]): List[Any] = xs match { 
    case List() => List() 
    case (y :: ys) :: yss => flatten(y :: ys) ::: flatten(yss) 
    case y :: ys => y :: flatten(ys) 
    } 
+3

我認爲最優雅的解決方案 – Vic

+0

'(x :: ys)::: yss'意味着「如果它是一個元素列表後跟另一個列表」? (因爲'()'表示元組AFAIK不在列表中) –

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