遍历时对嵌套列表对象进行计数

Counting Nested List Objects While Traversing

提问人:Dominick 提问时间:1/28/2020 更新时间:1/28/2020 访问量:439

问:

我正在用 C# 处理一个项目,其中我有一个带有属性的对象,其中一个被调用,它与父对象相同。例如:Children

public class ObjectInformation
{
   public string FullName {get; set;}
   public string FriendlyName {get; set;}
   public List<ObjectInformation> Children {get;}
}

我已经有了一个将根对象展平成简单列表的方法:

public static IEnumerable<ObjectInformation> Flatten(List<ObjectInformation> objs)
{
   var localCopy = Helpers.General.DeepCopy(objs);
   var finalList = new List<ObjectInformation>();
   foreach(var obj in localCopy)
   {
      if(obj.Children.Count > 0)
      {
         finalList.AddRange(Flatten(obj.Children));
         obj.Children.Clear();
      }

      obj.Parent = null;
      finalList.Add(obj);
   }

   return finalList;
}

我知道上述方法可能会得到改进,但它现在有效。但是,我现在要做的是遍历嵌套列表并输出数据,同时根据嵌套级别缩进行。

举个例子,假设根对象有两个对象,第一个对象有一个子对象,第二个对象有一个子对象,第二个对象也有一个子对象。我希望输出是这样的:

FullName of Root Object 1
   FullName of Child 1 of Root Object 1
FullName of Root Object 2
   FullName of Child 1 of Root Object 2
      FullName of Child 1 of Child 1 of Root Object 2

为了进行缩进,我需要某种计数器来确定层的嵌套深度。不过,我一直使用递归方法遇到问题,因为在每次调用时,变量都会重置。我在想,也许我需要使用静态变量来跟踪嵌套级别。不过,我看到的问题是,当它回溯时,静态变量仍将具有其达到的最深级别的值。

我有点不知所措,不知道该如何进行,尽管我确信这可能是我目前无法想象的简单解决方案;我通常不使用/需要递归,所以我没有太多实际使用它的经验。

您提供的任何帮助/建议将不胜感激。

谢谢

C# 递归 格式嵌 套列表

评论

0赞 Ak777 1/28/2020
您可以通过传递 ObjectInformation 元素在递归中执行此操作。我想该递归方法的返回值可以是一个字符串,因此您可以像您想要的那样输出。我可以给你一个关于如何实现这一点的伪代码,但我坚持要你试一试这种方法(也许,如果这是你最初的意图,你可以忽略 Flattern 方法)
0赞 jdweng 1/28/2020
向类 ObjectInformation 添加一个名为 LEVEL 的属性。然后在递归方法中添加一个名为 level 的参数,每次递归都会增加该参数。然后,当您打印结果时,请执行以下操作: Console.WriteLine(“{0} {1}”, new string(“ ”, 5 * level), line);因此,代码将为每个级别缩进 5 个字符。

答:

3赞 Jawad 1/28/2020 #1

我推荐一种方法,该方法采用对象并使用定义的空格打印每个对象。每次深入对象时,递归调用都会增加空间量。x

    public static void Print(this ObjectInformation parent, int spacing = 2)
    {
        Console.WriteLine($"{new string(' ', spacing)}{parent.FullName}");
        foreach (ObjectInformation child in parent.Children)
        {
            child.Print(spacing + 2);
        }
    }

评论

0赞 Dominick 1/28/2020
我知道这可能是这样简单的事情。谢谢,我要试一试,但这似乎正是我所需要的。
0赞 Ak777 1/28/2020 #2

我尝试了同样的练习,并得到了一个有效的结果。

public void PrintInfoList(IEnumerable<ObjectInformation> list)
    {
        var result = string.Join("\n", list.Select(item => GetPrintedFormat(item)));
        Console.WriteLine(result);
    }

    public string GetPrintedFormat(ObjectInformation info)
    {
        string printedFormat = string.Empty;
        printedFormat = $"Fullname of {info.FriendlyName} - {info.FullName}";
        if (info.Children != null && info.Children.Any())
        {
            childCount++;
            _formatter = $"\n{string.Empty.PadRight(childCount, '\t')}";
            printedFormat += $"{_formatter}{string.Join(_formatter, info.Children.Select(child => GetPrintedFormat(child)))}";
        }
        else
            if (childCount > 0) childCount--;

        return printedFormat;
    }

这是经过测试的工作解决方案。让我知道你对此的看法。

但我也喜欢用最简单的方式投票@Jawad。(拍手)