我看到Quickest way to compare two List<>,但我无法适应我的情况。我的问题是列表的类型不同。
我的列表是这样的:
List<Type1> firstList;
List<Type2> secondList;
以下是我现在所拥有的:
foreach (Type1 item in firstList)
{
if (!secondList.Any(x => x.Id == item.Id))
{
// this code is executed on each item in firstList but not in secondList
}
}
foreach (Type2 item in secondList)
{
if (!firstList.Any(x => x.Id == item.Id))
{
// this code is executed on each item in secondList but not in firstList
}
}
这是有效的,但是O(n^2)
。有没有办法让这个更有效率?我上面提到的问题中的解决方案是使用.Except
,但它不会使用lambda。
编辑: 我在上面提到了这一点,但这仍然被标记为重复。我没有两个相同对象的列表。我有两个不同对象的列表。 Type1和Type2是不同的类型。他们都有一个我需要匹配的ID。
答案 0 :(得分:1)
我建议将2种类型的ID转换为2种HashSets。那你可以
HashSet<int> a = new HashSet<int>(firstList.Select(o => o.Id));
HashSet<int> b = new HashSet<int>(secondList.Select(o => o.Id));
if (a.IsSubsetOf(b) && b.IsSubsetOf(a))
{
//Do your thing
}
答案 1 :(得分:0)
Except
- 方法有一个重载,它以IEqualityComparer<T>
作为最后一个参数。
MSDN中有一个示例:https://msdn.microsoft.com/en-us/library/bb336390.aspx
修改强>
可以创建匿名对象列表并将其与特殊IEqualityComparer<T>
进行比较。这是比较器类:
class MyEqualityComparer : IEqualityComparer<object>
{
#region IEqualityComparer<object> Members
bool IEqualityComparer<object>.Equals(object x, object y)
{
return (x as dynamic).Id == (y as dynamic).Id;
}
int IEqualityComparer<object>.GetHashCode(object obj)
{
return ((obj as dynamic).Id as object).GetHashCode();
}
#endregion
}
LINQ表达式应如下所示:
var result = lst1.Select(x => new { Id = x.Id, Obj = x })
.Except(lst2.Select(x => new { Id = x.Id, Obj = x }),
new MyEqualityComparer())
.Select(x => (x as dynamic).Obj as Type1);
我知道,在这种情况下使用动态是一种不好的风格,你可以毫无问题地将它改为实际类型。
答案 2 :(得分:0)
我不确定可用的C#/ Linq方法。从算法的角度来看,您可以对两个列表进行排序(通常为O(n*log(n))
)。然后你只需要扫描列表(线性,又名O(m+n)
,其中m
是列表1中的元素数量,n
列表2中的元素数量)。假设列表1是较长的列表,则总复杂度为O(m*log(m))
。
根据C#HashSet的实现,Murdock的答案可能会更快。