2016-12-02 3 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 s или если экземпляр B не имеет A s.

Для простоты предположим, что значение, которое я хочу произвести, представляет собой строку формы 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") 

Я попытался achiving это используя для понимания, но так как flatMap ИНГ над пустым Seq не дает значения, которое я должен был повернуть пустым Seq s в непустые. Код получился сложным и длинным.

Мой вопрос в том, что является лучшим способом для этого? Есть ли какая-то структура данных, которая может помочь сделать это проще?

Спасибо.

+0

Вы можете попробовать сопоставить шаблон по последовательностям as/bs и реализовать соответствующее поведение для пустых/непустых случаев. – jarandaf

+0

@jarandaf ok Я думаю, что понимаю, что вы имеете в виду, но я думаю, что это приведет к множеству вложенных для понимания (или просто 'flatMap') и шаблонов. Это будет работать, но я ищу что-то большее elegane \ idiomatic (особенно, если у вас больше трех гнезд). – Dani

+0

вывод '' c1 - - '' предполагает, что 'C' знает, сколько вложенных уровней находится ниже него. Это известно? – maasg

ответ

2

Я думаю, что это зависит от того, что вам нужно. Я превратил ваши классы в классы классов, чтобы упростить сопоставление шаблонов.

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") 
} 
Смежные вопросы