2016-12-02 64 views
1

我有以下問題,這我不知道如何優雅的模型:如何遍歷嵌套對象的所有組合?

說我有以下類:

class A(v: String) 
class B(v: String, as: Seq[A]) 
class C(v: String, bs: Seq[B]) 

鑑於C一個實例我想爲每個組合的值的C x B x A。即使C實例沒有任何B或者如果B實例沒有任何A,我也希望產生一個值。

爲了簡單起見,假設我想要生成的值是一個形式爲c.v - b.v - a.v的字符串。

換句話說 - 我正在尋找一種方式來實現以下方法:

def produce(c: C): List[String] = ??? 

這樣的:

val c1 = new C(v = "c1", bs = Seq.empty) 
produce(c1) // List("c1 - - ") 

val c2 = new C(
    v = "c1", 
    bs = Seq(new B(v = "b1", as = Seq.empty), new B(v = "b2", as = Seq.empty)) 
) 

produce(c2) // List("c1 - b1 - ", "c1 - b2 - ") 


val c3 = new C(
    v = "c1" 
    bs = Seq(
    new B(v = "b1", as = Seq(new A("a1"), new A("a2))) 
    new B(v = "b2", as = Seq(new A("a3"), new A("a4))), 
) 
) 

produce(c3) // List("c1 - b1 - a1", 
      //  "c1 - b1 - a2", 
      //  "c1 - b2 - a3", 
      //  "c1 - b2 - a4") 

我想這使用了理解,但由於flatMap荷蘭國際集團achiving在空的Seq不會產生一個值,我不得不將空的Seq s變成非空值。代碼變得複雜而漫長。

我的問題是做這件事的最好方法是什麼?是否有一些數據結構可以使這個更簡單?

謝謝。

+0

您可以嘗試對as/bs序列進行模式匹配,併爲空/非空案例實施相應的行爲。 – jarandaf

+0

@jarandaf好吧我想我理解你的意思,但我認爲這會導致一些嵌套的理解(或者簡單的'flatMap's)和模式數學。這將工作,但我正在尋找更elegane \慣用的東西(特別是如果你有更多的三個嵌套)。 – Dani

+0

輸出''c1 - - 「'假定'C'知道它下面有多少嵌套層次。這是一個已知的? – maasg

回答

2

我認爲這取決於你在做什麼。我把你的類變成了case類,以使模式匹配更容易。

sealed abstract class VSet 
case class A(v: String) extends VSet 
case class B(v: String, as: Seq[A]) extends VSet 
case class C(v: String, bs: Seq[B]) extends VSet 

def produce(vset: VSet, prefix: String = ""): Seq[String] = vset match { 
    case C(v, bs) => if (bs.isEmpty) Seq(s"$v -") 
        else bs.flatMap(produce(_, s"$v => ")) 
    case B(v, as) => if (as.isEmpty) Seq(s"$prefix$v -") 
        else as.flatMap(produce(_, s"$prefix$v => ")) 
    case A(v) => Seq(s"$prefix$v") 
}