在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+:
vsSeq(complex)+
,List()
vsNil
和。view
+1很好的解决方案,但不是真正的railrec
,因为在尾部位置有一个嵌套的plant
调用。
stuff.view.flatMap(flatten).map(_.copy(nested = Nil))