Scala - 展平树状结构

时间:2015-09-06 08:11:02

标签: scala flatmap

我有一个我从Java库接收的树结构。我试图压扁它,因为我只对树的“关键”值感兴趣。树由以下零个或多个类组成:

class R(val key: String, val nodes: java.util.List[R]) {}

带有表示分支结尾的空节点列表。可以通过以下代码构建示例:

val sample =  List[R](
  new R("1",  List[R](
    new R("2",  List[R]().asJava),
    new R("3",  List[R](new R("4",  List[R]().asJava))
      .asJava)).asJava)).asJava

我在编写正确的方法和有效的方法时遇到了麻烦。这就是我到目前为止所做的:

def flattenTree(tree: List[R]): List[String] = {
  tree.foldLeft(List[String]())((acc, x) => 
             x.key :: flattenTree(x.nodes.asScala.toList))
}

然而,当我运行此代码时,尽管效率低下,但我仍然认为它不正确。我的结果最终是:

>>> flattenTree(sample.asScala.toList)
res0: List[String] = List(1, 3, 4)

这意味着由于某种原因我丢失了带有键“2”的节点。

有人可以推荐一种正确且更有效的展平这棵树的方法吗?

4 个答案:

答案 0 :(得分:3)

您无法在每次连续呼叫中添加累积密钥。请尝试以下方法:

def flattenTree(tree: List[R]): List[String] = {
  tree.foldLeft(List[String]())((acc, x) =>
             x.key :: flattenTree(x.nodes.asScala.toList) ++ acc)
}

生成结果:List(1, 3, 4, 2)

或者,如果正确的顺序很重要:

def flattenTree(tree: List[R]): List[String] = {
  tree.foldLeft(List[String]())((acc, x) =>
             acc ++ (x.key :: flattenTree(x.nodes.asScala.toList)))
}

生成结果:List(1, 2, 3, 4)

答案 1 :(得分:3)

您可以使用R定义一个展开flatMap对象的函数:

// required to be able to use flatMap on java.util.List
import scala.collection.JavaConversions._

def flatten(r: R): Seq[String] = {
  r.key +: r.nodes.flatMap(flatten)
}

这是一个平整一系列的功能:

def flattenSeq(l: Seq[R]): Seq[String] = l flatMap flatten

r.nodes.flatMap(flatten)Buffer,所以在它之前没有效率。它变成了二次复杂性。因此,如果订单不重要,则可以更有效地追加:def flatten(r: R): Seq[String] = r.nodes.flatMap(flatten) :+ r.key

答案 2 :(得分:1)

将每个R转换为Scalaz Tree,并致电flatten进行预订遍历。

import scala.collection.JavaConversions._
import scalaz._

def rTree(r: R): Tree[String] =
  Tree.node(r.key, r.nodes.toStream.map(rTree))

sample.flatMap(r => rTree(r).flatten): Seq[String]
// List(1, 2, 3, 4)

编辑:不幸的是,由于版本7.1.1中的a bug in scalaz,这会导致宽树的堆栈溢出。

答案 3 :(得分:1)

使用像<?php require_once("facebook.php"); $config = array(); $config['appId'] = '446766585xxxxxx'; <-- APP ID $config['secret'] = '6fc8646c63b5356b5264d73f0fxxxxxx'; <--- APP SECRET $config['fileUpload'] = false; // optional $fb = new Facebook($config); $params = array( "access_token" => "XXXXXX", <--- PAGE ACCESS TOKEN OR APP ACCESS TOKEN "message" => "Hello", "link" => "http://www.example.com", "picture" => "http://example.com/images/8.jpg", "name" => "Completed", "caption" => "www.example.com", "description" => "Description here." ); try { $ret = $fb->api('/113928402609xxxx/feed', 'POST', $params); <-- PAGE ID I HAVE HERE echo 'Successfully posted to Facebook'; } catch(Exception $e) { echo $e->getMessage(); } ?> 这样的Stream会如何:

scalaz