Golang中结构的递归函数

时间:2016-07-07 15:00:17

标签: recursion go

我有以下代码将<DataTemplate DataType="{x:Type ViewModels:DocumentViewModel}"> <StackPanel> <View:DocumentView x:Name="DocumentViewInstance"/> <i:Interaction.Triggers> <i:EventTrigger EventName="Loaded"> <i:InvokeCommandAction Command="{Binding Path=DataContext.ViewLoadedEventHandlerCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}" CommandParameter="{Binding ElementName=DocumentViewInstance}"/> </i:EventTrigger> </i:Interaction.Triggers> </StackPanel> </DataTemplate> 结构组织成层次结构。 *Widget返回小部件,其ID为调用方的parentID。层次结构最多可达4或5级。

Parent()

我想要实现的是一个函数,它将父级以及父级的父级等聚合到层次结构的顶部,并返回所有父ID的片段。由于我不知道层次结构的深度,我认为我需要某种程序化的递归来获取每个父级的父级,这将执行以下操作:

type Widget struct {
  ID int64
  ParentID int64
}

func (w *Widget) Parent() *Widget {
  // Returns the widget with an ID of w.ParentID
}

是否有更为惯用的方法来实现这一目标?

1 个答案:

答案 0 :(得分:2)

您只需要在层次结构中越走越高,直到到达根目录。假设Widget.Parent()返回nil,如果Widget是&#34; root&#34; (意思是它没有父母):

迭代解决方案

以下是带有简单for循环的解决方案:

func (w *Widget) AllParents() []*Widget {
    var ws []*Widget
    for parent := w.Parent(); parent != nil; parent = parent.Parent() {
        ws = append(ws, parent)
    }
    return ws
}

如果在&#34; root&#34;上调用此方法将返回nilzero value表示所有切片类型)。在其他情况下,它将返回&#34;路径&#34;来自直接父母的指向&#34; root&#34;

这是一个小小的测试程序。它创建了一个带有ID = 0的根小部件,一个带有ID = 1的孩子和一个&#34;孙子&#34;使用ID = 2,并在每个上打印AllParents()。为了实现Widget.Parent(),我使用了一个简单的&#34;小部件注册表&#34;地图。

按预期结果:

Parents of 0:
Parents of 1: 0
Parents of 2: 1 0

Go Playground 上试试。

var wreg = map[int64]*Widget{}

func (w *Widget) Parent() *Widget {
    // Returns the widget with an ID of w.ParentID
    return wreg[w.ParentID]
}

func main() {
    w := &Widget{0, -1}
    wreg[w.ID] = w
    w2 := &Widget{1, 0}
    wreg[w2.ID] = w2
    w3 := &Widget{2, 1}
    wreg[w3.ID] = w3

    printParents(w)
    printParents(w2)
    printParents(w3)
}

func printParents(w *Widget) {
    fmt.Printf("Parents of %d:", w.ID)
    for _, w := range w.AllParents() {
        fmt.Print(" ", w.ID)
    }
    fmt.Println()
}

递归解决方案

当然也可以使用递归来解决:

func (w *Widget) AllParents() []*Widget {
    if parent := w.Parent(); parent == nil {
        return nil
    } else {
        return append(parent.AllParents(), parent)
    }
}

此解决方案返回&#34;路径&#34; 从导致直接父母的

使用此实现运行上述测试程序,输出为:

Parents of 0:
Parents of 1: 0
Parents of 2: 0 1

Go Playground 上试试。