我遇到过必须合并的对象列表的情况。列表中的每个对象都有一个属性,用于说明在合并中应如何处理它。所以假设以下内容..
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被推到谷底)
我认为你应该把问题分解成更小的部分。例如,可以在单独的扩展方法中实现单个列表的级联规则。这是我未经测试的看法:
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();
}