2015-02-10 72 views
0

我有以下對象結構:斯卡拉 - 遞歸函數不返回對象

case class Node(id:Int,children:List[Node]) 

例子:

NodeA 
    id: 1 
    children:[ 
     NodeA1: 
      id: 2 
      children: 
       NodeA11 
       ... 
     ]  
     NodeB1: 
      id: 3 
      children:[] 
     NodeC1: 
      id: 17 
      children: [ 
       NodeC11: 
        id:11 
        children:[ 
         NodeC111: 
          id: 19 
          children: [] 
        ] 

      ] 
     ... 

我想創建一個遞歸循環,從而得到具有特定的節點Id,但我卡在如何保持運行功能,如果沒有找到iD,並且該對象在兒童列表上有任何對象。我的功能只能用於獲取第一個節點(例如:Id = 1)。

這裏就是我想要做的事:

def getNode(id:Int, node:Node) : Node = { 
    var result:Node = null 
    if(node.id == id){ 
     return node 
    } else if(node.children.size > 0){ 
     for(children <- node.children){ 
     result = getNode(id, children) 
     if(result.id == id){ 
      return result 
     } 
     } 
    } 
    return result 
}   
+0

仿照你真想當什麼也沒找到,返回'null'? – Bergi 2015-02-10 16:53:55

+0

它可能爲空,無或異常 – placplacboom 2015-02-10 16:55:14

回答

7

功能getNode真的應該返回Option[Node]佔搜索的idNode樹不見了。

而且在這種情況下,你可以編寫遞歸調用的選項:

def getNode(id:Int, node:Node): Option[Node] = 
    if (node.id == id) Some(node) 
    else node.children.collectFirst(Function.unlift(getNode(id, _))) 

在必要的情況下,你不需要爲列表長度檢查:只返回None/null,你檢查每一個孩子在循環之後(或者不要檢查是否沒有任何孩子)。

def getNode(id:Int, node:Node) : Option[Node] = { 
    if (node.id == id) Some(node) 
    else { 
    for (child <- node.children) { 
     val result = getNode(id, child) 
     // At this point `result` is Some(nodeWeAreLookingFor) 
     // if it is in the subtree of the current `child` 
     // or None otherwise 
     if (result.isDefined) return result 
    } 
    None 
    } 
} 

對於Java你當然可以取代Optionnull,但在斯卡拉這個想法,自然是Option

+0

那麼優雅......我只是想知道,如何編寫其他條件的命令?我在問,因爲我是java開發人員,我想在這些語言上做一個並行工作 – placplacboom 2015-02-10 17:05:39

+0

@placplacboom我已經爲命令性案例添加了一部分 – Kolmar 2015-02-10 17:23:02

+0

真棒並感謝您在for循環內幫助 – placplacboom 2015-02-10 17:26:29