我是Linq的新手,我尝试根据字段过滤两个列表中的记录。 每个列表都有一个ID,我想记录ID出现在一个列表中但不出现在另一个列表中的任何记录。 我只用一个ID列表就可以做到这一点:
List1 = _class1.getList1();
List2 = _class2.getList2();
(为了介绍目的,我使用的是一个我想摆脱的类,它有一个数据列表,还有一个ID的列表,我应该能够只用数据列表来做将list1与list2进行比较的两个语句,反之亦然)
var inList1ButNot2 = List1.IDList.Except(List2.IDList);
var inList2ButNot1 = List2.IDList.Except(List1.IDList);
我遇到麻烦的地方是使用数据列表来比较第二个列表的ID字段。我相信它应该是这样的:
var inList1ButNot2 = DataList1.Select(x => x.ID)
.Except(DataList2.Select(y => y.ID));
问题在于我没有把整个记录只是我正在比较的字段,我是否需要在之后单独选择每个字段,或者在语句中是否有一种方法可以选择记录如果ID出现在一个字段中列表但不是另一个?
答案 0 :(得分:3)
所以你真正想要的是ExceptBy
方法;你希望能够在每个元素的投影上执行Except
,而不是在元素iteself上执行public static IEnumerable<TSource> ExceptBy<TSource, TKey>(
this IEnumerable<TSource> source,
IEnumerable<TSource> other,
Func<TSource, TKey> selector,
IEqualityComparer<TKey> comparer = null)
{
comparer = comparer ?? EqualityComparer<TKey>.Default;
var set = new HashSet<TKey>(other.Select(selector), comparer);
foreach (var item in source)
if (set.Add(selector(item)))
yield return item;
}
。以下是这种方法的实现:
var inList1ButNot2 = DataList1.ExceptBy(DataList2, item => item.ID);
var inList2ButNot1 = DataList2.ExceptBy(DataList1, item => item.ID);
现在你可以做到:
{{1}}
答案 1 :(得分:2)
可能有更好的方法,但是:
var inList1ButNot2 = DataList1.Where(x => !(DataList2.Any(y => y.ID == x.ID)));
注意:我是自由的,所以可能会有拼写错误。
答案 2 :(得分:0)
var list1 = new List<Asd>();
var list2 = new List<Asd>();
var asd = new Asd() {Id = 1, Name = "asd"};
var asd2 = new Asd() {Id = 2, Name = "asd"};
var asd3 = new Asd() {Id = 3, Name = "asd"};
var asd4 = new Asd() {Id = 4, Name = "asd"};
var asd5 = new Asd() {Id = 5, Name = "asd"};
list1.Add(asd);
list1.Add(asd2);
list1.Add(asd3);
list2.Add(asd);
list2.Add(asd4);
list2.Add(asd5);
var onlyInFirstList = list1.Where(x => !list2.Any(y => y == x));
var onlyInSecondList = list2.Where(x => !list1.Any(y => y == x));
这应该有效,但不完美但有效:)
答案 3 :(得分:0)
您可以尝试这样的事情。
public void Test(List<List1> list1, List<List2> list2)
{
var result = from l1 in list1
where list2.All(l2 => l1.Id != l2.Id)
select l1;
}
或者,如果你有两个属性(我假设它们是不同的类型?)你可以返回一个匿名类型,并从调用者实例返回属性
public void Test(List<List1> list1, List<List2> list2)
{
var result = from l1 in list1
where list2.All(l2 => l1.Id != l2.Id)
select new
{
l1.Id,
l1.OtherField1,
Test = 10.5, //Example declare new field
SomethingElse = this.PropertyXyz; //Set new field = instance property
};
}
答案 4 :(得分:0)
不是重写Except
中的逻辑(以及所有其他设置操作),而是允许可以为其他类和选择器重用的东西,考虑以下内容:
private class LambdaComparer<T, U> : IEqualityComparer<T>
{
private Func<T, U> selector;
public LambdaComparer(Func<T, U> selector)
{
this.selector = selector;
}
public bool Equals(T x, T y)
{
if (x == null && y == null) return true;
if (x == null || y == null) return false;
return EqualityComparer<U>.Default.Equals(selector(x), selector(y));
}
public int GetHashCode(T obj)
{
if (obj == null) return 0;
return EqualityComparer<U>.Default.GetHashCode(selector(obj));
}
}
var inList1ButNot2 = List1.IDList.Except(
List2.IDList,
new LambdaComparer<ClassWithID, int>(w => w.ID));
答案 5 :(得分:-1)
你可以尝试这样的事情
list1 = list1.Union(list2).Distinct().ToList();