LINQ,选择具有多种可能结果的多个

本文关键字:结果 选择 LINQ | 更新日期: 2023-09-27 17:56:01

我遇到过必须合并的对象列表的情况。列表中的每个对象都有一个属性,用于说明在合并中应如何处理它。所以假设以下内容..

enum Cascade {
  Full,
  Unique,
  Right,
  Left
}
class Note {
  int Id { get; set; }
  Cascade Cascade { get; set; }
  // lots of other data.
}
var list1 = new List<Note>{
 new Note {
   Id = 1,
   Cascade.Full,
   // data
 },
 new Note {
   Id = 2,
   Cascade.Right,
   // data
 }
};
var list2 = new List<Note>{
  new Note {
   Id = 1,
   Cascade.Left,
   // data
  }
};
var list3 = new List<Note>{
  new Note {
    Id = 1,
    Cascade.Unique,
    // data similar to list1.Note[0]
  }
}

那么,我会有一个方法...

Composite(this IList<IList<Note>> notes){
  return new List<Note> {
      notes.SelectMany(g => g).Where(g => g.Cascade == Cascade.All).ToList()
      // Here is the problem... 
      .SelectMany(g => g).Where(g => g.Cascade == Cascade.Right)
      .Select( // I want to do a _LastOrDefault_ )
      // continuing for the other cascades. 
  }
}

这就是我迷路的地方。我需要做多个SelectMany语句,但我不知道该怎么做。但这是预期的行为

Cascade.Full

无论如何,Note都将出现在最终系列中。

Cascade.Unique

Note将在最终集合中出现一次,忽略任何重复项。

Cascade.Left

Note将位于最终集合中,第一个实例取代后续实例。(因此,注释1,2,3是相同的。注1被推通)

Cascade.Right

Note将位于最终集合"最后一个实例取代重复项"中。(所以注1、2、3是相同的。注3被推到谷底)

LINQ,选择具有多种可能结果的多个

我认为你应该把问题分解成更小的部分。例如,可以在单独的扩展方法中实现单个列表的级联规则。这是我未经测试的看法:

public static IEnumerable<Note> ApplyCascades(this IEnumerable<Note> notes)
    {
        var uniques = new HashSet<Note>();
        Note rightToYield = null;
        foreach (var n in notes)
        {
            bool leftYielded = false;
            if (n.Cascade == Cascade.All) yield return n;
            if (n.Cascade == Cascade.Left && !leftYielded)
            {
                yield return n;
                leftYielded = true;
            }
            if (n.Cascade == Cascade.Right)
            {
                rightToYield = n;
            }
            if (n.Cascade == Cascade.Unique && !uniques.Contains(n))
            {
                yield return n;
                uniques.Add(n);
            } 
        }
        if (rightToYield != null) yield return rightToYield;
    } 
}

此方法将允许实现原始扩展方法,如下所示:

    List<Note> Composite(IList<IList<Note>> notes)
    {
        var result = from list in notes
                     from note in list.ApplyCascades()
                     select note;
        return result.ToList();
    }