迭代时从对象列表中删除元素

时间:2018-06-14 21:01:20

标签: c# list

我有一个id / parents列表,我正在迭代外部扩展。这个列表可以有大约11 000行,这就是为什么我需要删除一些元素,所以我只显示我需要的那些。

元素列表:

FlatData[] elements = new FlatData[]
{
   new FlatData {Id = 3, ParentId = 1, Text = "A"}, 
   new FlatData {Id = 4, ParentId = 1, Text = "D"},
   new FlatData {Id = 5, ParentId = 2, Text = "E"},
   new FlatData {Id = 7, ParentId = 2, Text = "G"},
   new FlatData {Id = 8, ParentId = 4, Text = "H"},
   new FlatData {Id = 9, ParentId = 8, Text = "H"},
   new FlatData {Id = 10, ParentId = 8, Text = "I"},
   new FlatData {Id = 11, Text = "I"},
};

虽然我正在迭代,但我想删除一些元素,以便它们不会被处理或显示,但我要删除的元素仍然存在于输出中!

这里的代码通过元素迭代:

int firstDepth = 0;

IEnumerable <DeepNodeData> nodes = elements.Where(x => x.Id >= 4).RecursiveJoin(element => element.Id,
     element => element.ParentId,
    (FlatData element, int index, int depth, IEnumerable<DeepNodeData> children) =>
     {
          int  position;

          if(depth == 0){
            firstDepth++;
          }

          if(firstDepth > 0){
              position= Array.FindIndex(elements, row => row.Id == index);
              elements.Skip(position);
          }

          return new DeepNodeData()
          {
              Id = element.Id,
              Index = index,
              Text = element.Text,
          };
    });

我只知道作为根父母的起始位置(id = 4)。一旦我有了深度值,我只会知道要删除的元素的位置。我们的想法是只显示附加到id = 4的子项。这里是我应该在最后得到的元素,应该处理它以构建我的树视图:

FlatData[] elements = new FlatData[]
 {
     new FlatData {Id = 4, ParentId = 1, Text = "D" },
     new FlatData {Id = 8, ParentId = 4, Text = "H" },
     new FlatData {Id = 9, ParentId = 8, Text = "H" },
 };

The Recusive Extension:

public static IEnumerable<TResult> RecursiveJoin<TSource, TKey, TResult>(this IEnumerable<TSource> source,
     Func<TSource, TKey> parentKeySelector,
     Func<TSource, TKey> childKeySelector,
     Func<TSource, int, int, IEnumerable<TResult>, TResult> resultSelector)
  {
    return RecursiveJoin(source, parentKeySelector, childKeySelector,
       resultSelector, Comparer<TKey>.Default);
  }

  public static IEnumerable<TResult> RecursiveJoin<TSource, TKey, TResult>(this IEnumerable<TSource> source,
     Func<TSource, TKey> parentKeySelector,
     Func<TSource, TKey> childKeySelector,
     Func<TSource, int, int, IEnumerable<TResult>, TResult> resultSelector,
     IComparer<TKey> comparer)
  {
    // prevent source being enumerated more than once per RecursiveJoin call
    source = new LinkedList<TSource>(source);

    // fast binary search lookup
    SortedDictionary<TKey, TSource> parents = new SortedDictionary<TKey, TSource>(comparer);
    SortedDictionary<TKey, LinkedList<TSource>> children
       = new SortedDictionary<TKey, LinkedList<TSource>>(comparer);

    foreach (TSource element in source)
    {
      parents[parentKeySelector(element)] = element;

      LinkedList<TSource> list;

      TKey childKey = childKeySelector(element);

      if (!children.TryGetValue(childKey, out list))
      {
        children[childKey] = list = new LinkedList<TSource>();
      }

      list.AddLast(element);
    }

    // initialize to null otherwise compiler complains at single line assignment
    Func<TSource, int, IEnumerable<TResult>> childSelector = null;

    childSelector = (TSource parent, int depth) =>
    {
      LinkedList<TSource> innerChildren = null;

      if (children.TryGetValue(parentKeySelector(parent), out innerChildren))
      {
        return innerChildren.Select((child, index)
           => resultSelector(child, index, depth , childSelector(child, depth + 1)));
      }
      return Enumerable.Empty<TResult>();
    };

    return source.Where(element => !parents.ContainsKey(childKeySelector(element)))
       .Select((element, index) => resultSelector(element, index, 0 ,childSelector(element, 1)));
  }

0 个答案:

没有答案