2014-10-08 75 views
0

我是相當新的Scala和我想分析的情況下類的列表:解析名單

abstract class D 
case class D0(a: Int, b: Int) extends D 
case class D2(c: String, d: Int) extends D 
case class D3(e: Int, f: String) extends D 
case class D4(e: String, f: String, g: Int) extends D 

我想分析列表[d]的實例。 有一個在列表中的一個特殊的順序可以由BNF狀符號進行說明:

rep(D0 -> D4 -> rep(D2 -> opt(rep(d3)))) 

D0之後D4之後是1-n的D2,每個D2隨後用1-N D3等...

我想創建類型的列表:

type T0 = (D0, D4, List[(D2, List[D3])]) 

到目前爲止,我發現所有的解決方案是醜陋的和有狀態。 經驗豐富的Scala開發人員如何實現這一目標?

謝謝

+0

你從什麼分析?也就是說,你的輸入格式是什麼? – sjrd 2014-10-08 20:14:48

+1

'List [D]'與您提出的結構不同。列表是一個列表。你的結構是別的。 – Daenyth 2014-10-08 20:24:45

+0

列表[D]是從基於文件的遺留數據庫導入的,具有不同的記錄類型,實現了分層數據庫模型。 – Volker 2014-10-09 09:37:30

回答

4

這看起來太醜陋了我(假設我理解正確的問題,這不是通常被稱爲解析):

type T1 = (D2, List[D3]) 

// MatchError if the list doesn't look the way you expected 
def matchList(l: List[D]): List[T0] = l match { 
    case (d0: D0) :: (d4: D4) :: tail => 
    val (d2d3s, tail1) = matchD2D3s(tail) 
    (d0, d4, d2d3s) :: matchList(tail1) 
    case Nil => Nil 
} 

def matchD2D3s(l: List[D]): (List[T1], List[D]) = l match { 
    case (d2: D2) :: tail => 
    val (d3s, tail1) = tail.span(_.isInstanceOf[D3]) 
    val (otherD2D3s, tail2) = matchD2D3s(tail1) 
    ((d2, d3s) :: otherD2D3s, tail2) 
    case l => (Nil, l) // no d2s 
} 
+0

我仍然需要驗證所提出的解決方案,也許在這個特殊情況下可以。對於功能性scala來說,它並不是很容易,特別是如果案例數量會增加的話。 – Volker 2014-10-09 09:38:16