2015-02-10 3 views
0

я иметь следующую структуру объекта:Scala - рекурсивная функция не возвращает объект

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, но я застрял в том, как продолжать работу fuction, если 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

+0

это может быть null, none или исключение – placplacboom

ответ

7

Функция getNode действительно должен возвращать Option[Node] на счет для поисков в id отсутствующих в Node дерева.

И в этом случае вы можете составить Параметры рекурсивных вызовов:

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 вы можете конечно заменить Option с null, но в Scala эта идея естественно моделируется Option

+0

Так элегантно ... Мне было просто интересно, как закодировать условие else на императивном пути? я спрашиваю, потому что я разработчик Java, и я бы сделал параллель на этих языках. – placplacboom

+0

@placplacboom. Я добавил часть для императивного случая. – Kolmar

+0

Удивительный и спасибо за помощь – placplacboom

Смежные вопросы