【问题标题】:Best practice recursive flattening of linked list in c# [duplicate]c#中链表的最佳实践递归展平[重复]
【发布时间】:2015-01-24 10:49:01
【问题描述】:

我构建了一个数据结构,其中主类TaskHolder, 包含一个List<Task>Task 包含另一个List<Task>Name。 是否有可以将所有嵌套名称检索到扁平字符串数组中的 LINQ 单行代码?

这是基本结构:

Public class TaskHolder
  List<Task>

Public class Task
  String Name
  List<Task>

【问题讨论】:

  • 所以可以无限嵌套级别?
  • @PetSerAl 你从我嘴里说出来了
  • 保证没有周期?
  • 这只是重复的一个例子。 “LINQ recusive one-liner”至少每两周询问一次。

标签: c# linq linked-list


【解决方案1】:

看起来如果没有递归就无法实现。可以是这样的:

    static IEnumerable<string> Flatten(Task task)
    {
        return new[] {task.Name}.Concat(task.Tasks.SelectMany(Flatten));
    }

    //.. and then
    var allNames = Flatten(taskHolder.Task);

【讨论】:

  • @MartinLiversage 为什么递归看起来不递归? ;)
  • 像魅力一样工作。我用 for each 循环封装了这个 Helper 以迭代列表中的所有任务并将其全部连接到一个 IEnumerable 中。
【解决方案2】:

您也可以编写自己的 LINQ 扩展方法来做这种事情,并使用堆栈之类的东西来避免显式递归(如果嵌套很深则更好):

  public static class LinqExtensions
  {
    public static IEnumerable<TP> FlattenProperties<T, TP>(this IEnumerable<T> outers,
        Func<T, TP> propertySelector, Func<T, IEnumerable<T>> innersSelector)
    {
      Stack<T> stack = new Stack<T>(outers);
      while (stack.Any())
      {
        T outer = stack.Pop();

        TP prop = propertySelector(outer);
        yield return prop;
        if (innersSelector(outer) != null)
        {
          foreach (var inner in innersSelector(outer))
            stack.Push(inner);
        }
      }
    }
  }

你可以这样写:

TaskHolder th = new TaskHolder() { ... };
var names = th.Tasks.FlattenProperties(x => x.Name, x => x.Tasks).ToList();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-12-20
    • 2011-02-13
    • 2010-11-11
    • 2012-09-10
    • 2012-03-18
    • 2011-07-21
    • 2011-01-28
    • 2011-01-10
    相关资源
    最近更新 更多