在Scala中展平嵌套对象

在Scala中展平嵌套对象,scala,flatten,flatmap,Scala,Flatten,Flatmap,给定如下所示的复杂对象: case class Complex ( id: Long, name: String, nested: Seq[Complex] ) 在行动中,这可能会变成这样: val stuff = List( Complex(1, "name1", List( Complex(2, "name2", List()), Complex(3, "name3", List(

给定如下所示的复杂对象:

case class Complex
(
  id: Long,
  name: String,
  nested: Seq[Complex]
)
在行动中,这可能会变成这样:

val stuff =
  List(
    Complex(1, "name1",
      List(
        Complex(2, "name2", List()),
        Complex(3, "name3",
          List(
            Complex(4, "name4", List())
          )
        )
      )
    )
  )
我需要把它变成一个简单的
复杂的
对象列表,把所有的孩子/孙子都拉上来

val flattened =
  List(
    Complex(1, "name1", List()),
    Complex(2, "name2", List()),
    Complex(3, "name3", List()),
    Complex(4, "name4", List()),
  )
你对我如何实现这一目标有什么线索/想法吗

我尝试过的其他解决方案似乎只做简单的列表嵌套。 我尝试过的事情:


这些似乎都产生了与我开始时相同的列表。

这里平坦化输入序列的困难在于有必要删除结果列表中的嵌套引用。这可以通过使用
nested
=空列表复制原始对象并展平所有序列来完成:

def flatten(obj: Complex): Seq[Complex] = {
  val unnested = obj.copy(nested = List())
  Seq(unnested) ++ obj.nested.flatMap(flatten)
}

println(stuff.flatMap(flatten))

List(
  Complex(1,name1,List()),
  Complex(2,name2,List()),
  Complex(3,name3,List()),
  Complex(4,name4,List())
  )
其中:

scala> stuff.flatMap(flattenComplex _)
res0: List[Complex] = List(Complex(1,name1,List()), Complex(2,name2,List()), Complex(3,name3,List()), Complex(4,name4,List()))
使用尾部递归

def flatten(source: Seq[Complex], dest: List[Complex]): List[Complex] = source match {
  case Nil => dest
  case x :: xs => flatten(xs, flatten(x.nested, dest :+ x.copy(nested = Nil)))
}
flatten(stuff, List())

我的解决方案与已经发布的解决方案基本相同,但在展平单个元素时,避免了将head元素放入单个集合的低效性(不太明显):

def flatten(complex: Complex): Seq[Complex] =
  complex +: complex.nested.flatMap(flatten)
相对于

def flatten(complex: Complex): Seq[Complex] =
  Seq(complex) ++ complex.nested.flatMap(flatten)
然后按如下方式使用:

stuff.view.flatMap(flatten).map(_.copy(nested = Nil))
请注意,我还推迟了使用空列表(
Nil
)替换
嵌套的
元素,从而与实际的展平分离,同时仍然避免了不必要的利用
视图的双过程(更多信息)


您可以使用此解决方案。

在我测试解决方案的时间内,此页面中出现的单词
flat
的次数已增加到32次。:-)这正是我要找的!谢谢大家!@Antott只是想指出:这个解决方案是一个递归函数,它是迭代的理想函数方法。关于
complex+:
vs
Seq(complex)+
List()
vs
Nil
。view
+1很好的解决方案,但不是真正的
railrec
,因为在尾部位置有一个嵌套的
plant
调用。
stuff.view.flatMap(flatten).map(_.copy(nested = Nil))