递归遍历树并返回找到的所有值的未静音列表?可能?

时间:2013-11-04 15:59:53

标签: recursion f# tree-traversal

我想知道这问题是否甚至可能存在。 我的问题是我似乎无法掌握如何处理给定输入值可以有多个子节点的事实。通过使用可变的SortedSet变量可以很容易地解决问题,如下所示。但我真的想知道这是否可能通过纯递归和创建新的未静音列表或类似问题来解决。我希望我的问题很清楚。我担心我不知道这是不可能的简单结论。 正如您所见,if(true)将返回一个列表,但else将返回一个列表列表。所以下面的代码不处于工作状态。

let someSet = new System.Collections.Generic.SortedSet<string>()
let rec children(value:string,listSoFar) =
    printfn "ID: %A" value 
    someSet.Add(value) works fine of course.
    let newList = List.append listSoFar [value]
    if(not (hasChildren(value))) then 
        newList
    else
        let tmpCollection = database.GetCollection<Collection>("Collection")
        let tmpQuery = Query.EQ("Field",BsonValue.Create(value))
        let tmpRes = tmpCollection.Find(tmpQuery)
        [ for child in tmpRes do
            yield children(child.Value,newList) ]


let resultList = children("aParentStartValue",[]) 
//Or do i need to use someSet values?

1 个答案:

答案 0 :(得分:3)

除非树嵌套得非常深(在这种情况下,这样效率很低),您可以将代码编写为递归F#序列表达式,使用yieldyield!生成元素

let rec children (value:string) = seq {
    // Produce the current value as the next element of the sequence
    yield value
    if hasChildren value then 
      // If it has children, then get all the children
      let tmpCollection = database.GetCollection<Collection>("Collection")
      let tmpQuery = Query.EQ("Field",BsonValue.Create(value))
      let tmpRes = tmpCollection.Find(tmpQuery)
      // For each child, generate all its sub-children recursively
      // and return all such elements as part of this sequence using 'yield!'
      for child in tmpRes do
        yield! children child.Value }

// Using 'List.ofSeq' to fully evaluate the lazy sequence
let resultList = List.ofSeq (children "aParentStartValue")

如果树嵌套得更深,那么情况就更难了。迭代所有子项时,您需要将目前收集的列表传递给第一个子项,获取结果,然后将结果列表传递给下一个子项(使用List.fold之类的东西)。但上述内容很简洁,在大多数情况下都应该有效。