我有两个用CustomsObjects填充的通用列表。
我需要在第三个列表中检索这两个列表(第一个列表中的项目,第二个列表中的项目)之间的差异。
我本以为使用.Except()是个好主意,但我看不到如何使用它。
我有两个用CustomsObjects填充的通用列表。
我需要在第三个列表中检索这两个列表(第一个列表中的项目,第二个列表中的项目)之间的差异。
我本以为使用.Except()是个好主意,但我看不到如何使用它。
Answers:
使用Except是完全正确的方法。如果您的类型覆盖Equals和GetHashCode,或者您只对引用类型相等感兴趣(即,如果两个引用引用完全相同的对象,则两个引用只是“相等”),您可以使用:
var list3 = list1.Except(list2).ToList();
如果您需要表达自定义的相等性想法(例如,通过ID),则需要实现IEqualityComparer<T>。例如:
public class IdComparer : IEqualityComparer<CustomObject>
{
public int GetHashCode(CustomObject co)
{
if (co == null)
{
return 0;
}
return co.Id.GetHashCode();
}
public bool Equals(CustomObject x1, CustomObject x2)
{
if (object.ReferenceEquals(x1, x2))
{
return true;
}
if (object.ReferenceEquals(x1, null) ||
object.ReferenceEquals(x2, null))
{
return false;
}
return x1.Id == x2.Id;
}
}
然后使用:
var list3 = list1.Except(list2, new IdComparer()).ToList();
请注意,这将删除所有重复的元素。如果您需要保留重复项,则可能最简单的方法是从中创建集合list2并使用类似方法:
var list3 = list1.Where(x => !set2.Contains(x)).ToList();
您可以执行以下操作:
var result = customlist.Where(p => !otherlist.Any(l => p.someproperty == l.someproperty));
Any应该是一个All,如果你想那样做。这是因为第二个列表可以包含第一个列表中的项目,但是如果不是第一个列表中的项目,则它将立即为true p.someproperty != l.someproperty。这将导致返回两个列表中都存在的项目。对此提出支持的6个人感到羞耻。
我想强调一点很重要-使用Except方法将返回第一个中的项目,而第二个中的项目不会返回。它不会返回第二个没有出现在第二个中的元素。
var list1 = new List<int> { 1, 2, 3, 4, 5};
var list2 = new List<int> { 3, 4, 5, 6, 7 };
var list3 = list1.Except(list2).ToList(); //list3 contains only 1, 2
但是,如果您想获得两个列表之间的真正差异:
在第一个项目中没有第二个项目的项目,在第二个项目中没有第一个项目的项目。
您需要两次使用“除外”:
var list1 = new List<int> { 1, 2, 3, 4, 5};
var list2 = new List<int> { 3, 4, 5, 6, 7 };
var list3 = list1.Except(list2); //list3 contains only 1, 2
var list4 = list2.Except(list1); //list4 contains only 6, 7
var resultList = list3.Concat(list4).ToList(); //resultList contains 1, 2, 6, 7
或者,您可以使用HashSet的SymmetricExceptWith方法。但这会更改调用的集:
var list1 = new List<int> { 1, 2, 3, 4, 5};
var list2 = new List<int> { 3, 4, 5, 6, 7 };
var list1Set = list1.ToHashSet(); //.net framework 4.7.2 and .net core 2.0 and above otherwise new HashSet(list1)
list1Set.SymmetricExceptWith(list2);
var resultList = list1Set.ToList(); //resultList contains 1, 2, 6, 7
var list3 = list1.Where(x => !list2.Any(z => z.Id == x.Id)).ToList();
注意:list3将包含不在两个列表中的项目或对象。注意:ToList()不是toList()
由于Except扩展方法对两个IEumerables进行操作,因此在我看来它将是O(n ^ 2)运算。如果性能是一个问题(如果说您的列表很大),建议您从list1创建一个HashSet并使用HashSet的ExceptWith方法。
Enumerable.Except内部使用HashSet或类似用途。它绝对不使用朴素的O(n ^ 2)算法。
这是我的解决方案:
List<String> list1 = new List<String>();
List<String> list2 = new List<String>();
List<String> exceptValue = new List<String>();
foreach(String L1 in List1)
{
if(!List2.Contains(L1)
{
exceptValue.Add(L1);
}
}
foreach(String L2 in List2)
{
if(!List1.Contains(L2)
{
exceptValue.Add(L2);
}
}
有点晚了,但是这对我来说是可行的解决方案
var myBaseProperty = (typeof(BaseClass)).GetProperties();//get base code properties
var allProperty = entity.GetProperties()[0].DeclaringType.GetProperties();//get derived class property plus base code as it is derived from it
var declaredClassProperties = allProperty.Where(x => !myBaseProperty.Any(l => l.Name == x.Name)).ToList();//get the difference
在上面提到的代码中,我得到了我的基类和派生类列表之间的属性差异
var resultList = checklist.Where(p => myList.All(l => p.value != l.value)).ToList();
List<ObjectC> _list_DF_BW_ANB = new List<ObjectC>();
List<ObjectA> _listA = new List<ObjectA>();
List<ObjectB> _listB = new List<ObjectB>();
foreach (var itemB in _listB )
{
var flat = 0;
foreach(var itemA in _listA )
{
if(itemA.ProductId==itemB.ProductId)
{
flat = 1;
break;
}
}
if (flat == 0)
{
_list_DF_BW_ANB.Add(itemB);
}
}
如果两个列表都实现IEnumerable接口,则可以使用LINQ实现此目的。
list3 = list1.where(i => !list2.contains(i));
IEnumerable.Except代替。
Except是一个集操作,那么结果列表将有不同的值,如{'A','A','B','C'}.Except({'B','C'})收益{'A'}