【问题标题】:Find child of a object recursively c#递归查找对象的子对象c#
【发布时间】:2019-01-31 00:37:03
【问题描述】:

我想问你遍历 Parent 的每个子对象的最有效方法是什么。例如我有一个类是:

public class Asset
{
    public string Id { get; set; }

    public Asset Child { get; set; }
}

static void Main(string[] args)
{
     var x = new Asset() { Id = "1" };
     var y = new Asset() { Id = "2" };
     var z = new Asset() { Id = "3" };

     x.Child = y;
     y.Child = z;
     z.Child = null;

     var listOfChildItems = new List<Asset>();
     listOfChildItems = GetAllChildren(x);
}

static List<Asset> GetAllChildren(Asset asset)
{
   // TODO:
}

这个类可能包含 Child 包含另一个孩子等等。所以我想要的是递归获取子项的子项的整个列表,直到子项不等于空。

【问题讨论】:

  • 你试过什么?什么具体不起作用?
  • 如果你想递归地遍历对象树,使用递归方法听起来是个好主意。具体来说,返回 IEnumerable&lt;Asset&gt; 的迭代器方法可以解决问题。
  • 定义“最有效”。最少的代码行?最快的执行时间?消耗的内存最少?
  • @HimBromBeere 可能是这些参数中的每一个。
  • 通常你无法获得全部,如果你保存一些代码行可能会花费你的时间、内存,甚至可读性,反之亦然。

标签: c# recursion


【解决方案1】:
class Asset
{
    public Asset Child { get; set; } = null;
}

static void main (string[] args) 
{
     List<Asset> children = new List<Asset>();
     Asset asset = new Asset();
     while (asset.Child != null) 
     {
         asset = asset.Child;
         children.Add(asset);
     }
     //asset is now the bottom most child
}

【讨论】:

  • @Fildor 你怎么看那个?它检查孩子是否为空,将资产分配给不是null 的孩子,然后将其添加到children
【解决方案2】:
static IEnumerable<Asset> GetAllAssets(Asset asset)
{
    if (asset == null)
        yield break;

    yield return asset;
    foreach (Asset child in GetAllAssets(asset.Child))
        yield return child;
}

【讨论】:

  • 这不是最有效的方法。由于递归、收益返回和 foreach 循环,我会说这是效率较低的方法。
  • @MichałJarzyna 你为什么喜欢它?看看:stackoverflow.com/questions/410026/proper-use-of-yield-return
  • @Dongdong 因为应该是public static IEnumerable&lt;Asset&gt; GetAllAssets( Asset item ) { while( item.Child != null ) { item = item.Child; yield return item; } }
  • 哦。只需编辑它。:-)
  • @Dongdong 不,我不会。这会破坏马蒂亚斯的回答。我不知道他是否会接受。
【解决方案3】:
public class Asset
{
    public Asset Child { get; set; }

    public List<Asset> GetChildren()
    {
        return GetChildrenInternal(new List<Asset>(), this);
    }

    private List<Asset> GetChildrenInternal(List<Asset> children, Asset parent)
    {
        if (parent.Child?.Child != null)
        {
            children.Add(parent.Child);
            GetChildrenInternal(children, parent.Child);
        }

        return children;
    }
}

【讨论】:

  • 恕我直言,递归解决方案在这里不是最理想的。您可以不使用它并且同时更高效、更易读、更短。
【解决方案4】:
public static IEnumerable<T> GatherChild<T>(this T value, Func<T, T> selector)
    where T : class
{
    while (!(value is null))
    {
        yield return value;
        value = selector(value);
    }
}

public static IEnumerable<T> GatherSelfAndChildren<T>(this T value, Func<T, IEnumerable<T>> selector) => 
    selector(value).SelectMany(x => GatherSelfAndChildren(x, selector)).Prepend(value);

public static IEnumerable<T> GatherChildren<T>(this T value, Func<T, IEnumerable<T>> selector) => 
    selector(value).SelectMany(x => x.GatherSelfAndChildren(selector));

【讨论】:

    猜你喜欢
    • 2021-08-26
    • 2018-02-14
    • 2011-06-05
    • 2019-07-14
    • 2021-05-29
    • 2016-01-24
    • 1970-01-01
    • 2016-10-24
    • 1970-01-01
    相关资源
    最近更新 更多