提问者:小点点

递归方法C#的多个循环


我有一个对象,里面有多个嵌套对象。类:

public class Element
{
    public string Key { get; set; }
    public List<Element> SubElement { get; set; }

    [XmlIgnore]
    public ElementConfig ElementConfig { get; set; }

    [XmlIgnore]
    public Element ParentElement { get; set; }

}
public class SubElement
{
    public string Key { get; set; }
    public List<Element> Elements { get; set; }
}

[Serializable]
public class ElementConfig {
    public string Key { get; set; }
    public string Label { get; set; }
    public string TypeName { get; set; }
    public string IconName { get; set; }
}

其基础是,一个元素可以有多个子元素以及它们自己的ElementConfig。我想为每个元素填充ElementConfig,如下所示:

    private void Recursion(Element element)
    {
        //TODO: use recursion ??
        foreach (Element item in element.SubElement)
        {
            item.ElementConfig = navigationStructureConfig.ElementConfigs.SingleOrDefault(x => x.Key == item.Key);
            item.ParentElement = element;

            foreach (Element x in item.SubElement)
            {
                x.ElementConfig = navigationStructureConfig.ElementConfigs.SingleOrDefault(e => e.Key == x.Key);
                x.ParentElement = item;

                foreach (Element y in x.SubElement)
                {
                    y.ElementConfig = navigationStructureConfig.ElementConfigs.SingleOrDefault(e => e.Key == y.Key);
                    y.ParentElement = x;
                }
            }                
        }
    }

这是起作用的,但我想用一个递归的方法来做这件事。这可能吗?

根据@johnathan Barclay的建议编辑我使用以下方法:

element.ElementConfig = navigationStructureConfig.ElementConfigs.SingleOrDefault(x => x.Key == element.Key);

        foreach (var item in element.SubElement)
        {
            item.ParentElement = element;
            Recursion(item); 
        }

这有助于获取每个第一个子元素ElementConfig。现在发生的情况是以下子元素没有填充。


共2个答案

匿名用户

假设还需要为根元素设置elementconfig:

private void Recursion(Element element)
{
    element.ElementConfig = navigationStructureConfig.ElementConfigs
        .SingleOrDefault(x => x.Key == element.Key);
    
    foreach (var item in element.SubElement)
    {
        item.ParentElement = element;    
        Recursion(item); // Recurse here
    }
}

匿名用户

下面是一个通用的迭代解决方案:

public void PupulateConfigAndParent(Element element){
    foreach(var (item, parent) in DepthFirstWithParent(element, e => e.SubElement)){
        item.ElementConfig = navigationStructureConfig.ElementConfigs.SingleOrDefault(x => x.Key == item.Key);
        item.ParentElement = parent;
    }
}

    public static IEnumerable<(T Node, T Parent)> DepthFirstWithParent<T>(T self, Func<T, IEnumerable<T>> selector)
    {
        var stack = new Stack<(T Node, T Parent)>();
        stack.Push((self, self));
        while (stack.Count > 0)
        {
            var current = stack.Pop();
            yield return current;
            foreach (var child in selector(current.Node))
            {
                stack.Push((child, current.Node ));
            }
        }
    }

这样做的一个优点是可以对任何类型的树状结构重用泛型方法。注意,根节点将自己作为父节点。