Linq,选择两个列表之间的差异,在同一列表中选择相同,并选择重复相同的列表

时间:2013-05-08 12:12:14

标签: c# linq list merge equality

我想知道LINQ是否有可能实现以下目标:

newList: { [1], [2] }
oldList: { [2], [3], [4], [5] }
resultantList = { [1], [2, 2], [3], [4], [5] }

好的,这简直过分了。让我们说:

Class A
{
    public string Name;
    public IList<B> Items;
    public bool Equals(A obj)
    {
         return obj.Name == Name;
    }
}


newList<A> = {{ Name = "A", Items[1]}, { Name = "B", Items[1] }}
oldList<A> = {{ Name = "C", Items[2]}, { Name = "A", Items[2] }, { Name = "D", Items[1] }, { Name = "E", Items[1] },}
mergedList<A> = {{ Name = "A", Items[3]}, { Name = "B", Items[1]}, { Name = "C", Items[2]}, { Name = "D" , Items[1]}, { Name = "E" , Items[1]}}

请注意,对于Name =“A”的实例,列表实际上是两个列表的合并列表。秩序无关紧要,实际上平等更复杂。

我希望在类型上实现这一点(即在工作之下,但效率低下):

var fragments = newGeometryFragments.Except(oldGeometryFragments).ToList();
fragments.AddRange(oldGeometryFragments.Except(newGeometryFragments).ToArray());
var mergedFragments = (from newGeometry in newGeometryFragments
                       from oldGeometry in oldGeometryFragments
                       where newGeometry.Equals(oldGeometry)
                       select MergeGeometryFragments(newGeometry, oldGeometry)).ToArray();
 fragments.AddRange(mergedFragments);

2 个答案:

答案 0 :(得分:1)

您可以使用以下代码,假设您已填充oldListnewList

newList.Union(oldList) // unite the collections
   .GroupBy(x => x /*, ComparerInstance*/) // will group by unique elemens
   .Select(x => x.ToList()) // or .ToArray(), convert each group to array or list
   .ToList(); // return a list of lists/arrays

上面的代码将生成一个集合列表。每个集合都有一个或多个相等的元素,具体取决于newList.Union(oldList)中元素的出现次数。

如果您正在使用特定元素并希望控制它们的比较方式(确定相等),请将自定义IEqualityComparer<YourType>实例传递给GroupBy方法。

答案 1 :(得分:0)

您可以使用外部联接:

var oldList = new List<int?> { 2, 3, 4, 5 };
var newList = new List<int?> { 1, 2 };
var result = from all in oldList.Union(newList).OrderBy(num => num)
             join o in oldList on all equals o into gjOld
             from oldOuter in gjOld.DefaultIfEmpty()
             join n in newList on all equals n into gjNew
             from newOuter in gjNew.DefaultIfEmpty()
             select new { newVal = newOuter, oldVal = oldOuter };

在您实施EqualsGetHashCode或实施自定义IEqualityComparer<T>时,这也适用于自定义类。那么Nullable<int>技巧也是不必要的

Demo

newVal: 1   oldVal: 
newVal: 2   oldVal: 2
newVal:     oldVal: 3
newVal:     oldVal: 4
newVal:     oldVal: 5