根据一些共同的列和 return 个不匹配的项目比较两个不同的通用列表
Compare two different generic lists based on some common columns and return unmatched items
我有 2 个不同的通用列表,其中包含一些我想用于比较的公共字段和 return 来自其他列表的不匹配行,反之亦然。
第一个列表:列出 freightCharges
第二个列表:列出 shippingCharges
我想比较这两个列表,其中“家庭”在第二个列表中不匹配,并生成一个新的差异列表,我想在下一步中反之亦然,但以下查询不是 return在有差异的情况下进行任何操作:
var list0 = shippingCharges.Where(item => freightCharges.All(f => item.Buid == f.BUID && item.Catalog == (f.Catalog != null ? f.Catalog : null)
&& item.Productline == (f.ProductLine != null ? f.ProductLine : null)
&& item.Brand == (f.Brand != null ? f.Brand : null) && item.Family != (f.Family != null ? f.Family : null))).ToList();
There was some possibility of null so, I handled them as well.
我想将一个列表的每个列表项与另一个进行比较。我可以使用 foreach 循环,但我认为在 Linq 中会有同样的东西可用。
您必须重写所比较模型的 Equal 方法。请参阅 MSDocs 中的 link,了解有关如何以及为何这样做的更多信息。
https://docs.microsoft.com/en-us/dotnet/api/system.object.equals?view=net-6.0
我们以两个类为例:
public class ShippingCharges
{
public string ProductLine { get; set; }
public int Family { get; set; }
}
public class FreightCharges
{
public string Brand { get; set; }
public int? Family { get; set; }
}
我们添加一些值:
var ListA = new List<ShippingCharges>() {
new ShippingCharges()
{
ProductLine = "1",
Family = 1
},
new ShippingCharges()
{
ProductLine = "1",
Family = 2
},
};
var ListB = new List<FreightCharges>(){
new FreightCharges()
{
Brand = "2",
Family = 2
},
new FreightCharges()
{
Brand = "3",
Family = 3
},
};
添加一些 LINQ 扩展:
public static class LinqExtensions
{
public static IEnumerable<TSource> Except<TSource, VSource>(this IEnumerable<TSource> first, IEnumerable<VSource> second, Func<TSource, VSource, bool> comparer)
{
return first.Where(x => second.Count(y => comparer(x, y)) == 0);
}
public static IEnumerable<TSource> Contains<TSource, VSource>(this IEnumerable<TSource> first, IEnumerable<VSource> second, Func<TSource, VSource, bool> comparer)
{
return first.Where(x => second.FirstOrDefault(y => comparer(x, y)) != null);
}
public static IEnumerable<TSource> Intersect<TSource, VSource>(this IEnumerable<TSource> first, IEnumerable<VSource> second, Func<TSource, VSource, bool> comparer)
{
return first.Where(x => second.Count(y => comparer(x, y)) == 1);
}
}
获取列表 A 中不在列表 b 中的所有元素:
var newData = ListA.Except(ListB, (a,b) => a.Family == b.Family);
备注:f.Brand != null ? f.Brand : null
等于f.Brand ?? null
等于f.Brand
如果您将更频繁地使用它来处理不同的 类,我的建议是为此创建一个通用扩展方法,这样您就可以像标准 LINQ 方法一样重用它。如果您不熟悉扩展方法,请阅读 Extension Methods Demystified。
所以我们必须输入不同类型的序列。序列 1 中的对象具有 属性 X,序列中的对象具有 属性 Y。您可以检查属性 X 和 Y 的值是否相等。
要求:return 序列 1 中的所有对象,其 属性 X 的值不等于序列 2 中对象的任何 Y 值。将此与副连接-相反。
所以我们先为一侧做一个程序。然后我们用 Concat
重用它,反之亦然
public static WhereNotMatched<Touter, Tinner, TKey>(
this IEnumerable<Touter> outer,
IEnumerable<Tinner> inner,
Func<Touter,TKey> outerKeySelector,
Func<TInner,TKey> innerKeySelector)
{
return WhereNotMatched(outer, inner, outerKeySelector, innerKeySelector, null);
{
public static IEnumerable<Touter> WhereNotMatched<Touter, Tinner, TKey>(
this IEnumerable<Touter> outer,
IEnumerable<Tinner> inner,
Func<Touter,TKey> outerKeySelector,
Func<TInner,TKey> innerKeySelector
IEqualityComparer<TKey> comparer)
{
// if no comparer provided, use the default comparer
if (comparer == null) comparer = EqualityComparer<TKey>.Default;
// TODO: check outer != null, inner != null, etc.
// extract all inner keys, for efficient lookup put them in a HashSet<TKey>
HashSet<TKey> innerKeys = new HashSet(inner.Select(i => innerKeySelector(i)), comparer);
// return all outer that have no corresponding value in the HashSet
return outer.Where(o => !innerKeys.Contains(innerKeySelector(o));
}
用法:
假设在一个订购系统中您有 Products、Orders 和 OrderLines。每个 OrderLine 都有一个外键 ProductId。此 ProductId 指的是此 OrderLine 中提到的产品。每个订单包含零个或多个订单行。
IEnumerable<Order> orders = ...
IEnumerable<Product> products = ...
// Get all Products that have never been ordered yet
IEnumerable<OrderLine> orderLines = orders.SelectMany(order => order.OrderLines);
IEnumerable<Product> neverOrderedProducts = products.WhereNotMatched(orderLines,
product => product.Id,
orderLine => orderLine.ProductId);
以下是您要的更多内容:
IEnumerable<Student> maleStudents = ...
IEnumerable<Student> femaleStudents = ...
假设每个学生都有 PromCompanion
。我们不是老式的,所以一些男性学生有一个不是女性学生的 PromCompanion,同样,一些女性学生有一个非男性学生作为 PromCompanion。找到所有这些学生。
IEnumerable<Student> result = maleStudents.WhereNotMatched(femaleStudents,
man => man.PromCompanion,
woman => woman.PromCompanion)
// concat with vice-versa
.Concat(femaleStudents.WhereNotMatched(maleStudents,
woman => woman.PromCompanion,
man => man.PromCompanion));
IEnumreable<Student> uncompaniedStudents = maleStudents.WhereNon
我有 2 个不同的通用列表,其中包含一些我想用于比较的公共字段和 return 来自其他列表的不匹配行,反之亦然。
第一个列表:列出 freightCharges 第二个列表:列出 shippingCharges
我想比较这两个列表,其中“家庭”在第二个列表中不匹配,并生成一个新的差异列表,我想在下一步中反之亦然,但以下查询不是 return在有差异的情况下进行任何操作:
var list0 = shippingCharges.Where(item => freightCharges.All(f => item.Buid == f.BUID && item.Catalog == (f.Catalog != null ? f.Catalog : null)
&& item.Productline == (f.ProductLine != null ? f.ProductLine : null)
&& item.Brand == (f.Brand != null ? f.Brand : null) && item.Family != (f.Family != null ? f.Family : null))).ToList();
There was some possibility of null so, I handled them as well.
我想将一个列表的每个列表项与另一个进行比较。我可以使用 foreach 循环,但我认为在 Linq 中会有同样的东西可用。
您必须重写所比较模型的 Equal 方法。请参阅 MSDocs 中的 link,了解有关如何以及为何这样做的更多信息。
https://docs.microsoft.com/en-us/dotnet/api/system.object.equals?view=net-6.0
我们以两个类为例:
public class ShippingCharges
{
public string ProductLine { get; set; }
public int Family { get; set; }
}
public class FreightCharges
{
public string Brand { get; set; }
public int? Family { get; set; }
}
我们添加一些值:
var ListA = new List<ShippingCharges>() {
new ShippingCharges()
{
ProductLine = "1",
Family = 1
},
new ShippingCharges()
{
ProductLine = "1",
Family = 2
},
};
var ListB = new List<FreightCharges>(){
new FreightCharges()
{
Brand = "2",
Family = 2
},
new FreightCharges()
{
Brand = "3",
Family = 3
},
};
添加一些 LINQ 扩展:
public static class LinqExtensions
{
public static IEnumerable<TSource> Except<TSource, VSource>(this IEnumerable<TSource> first, IEnumerable<VSource> second, Func<TSource, VSource, bool> comparer)
{
return first.Where(x => second.Count(y => comparer(x, y)) == 0);
}
public static IEnumerable<TSource> Contains<TSource, VSource>(this IEnumerable<TSource> first, IEnumerable<VSource> second, Func<TSource, VSource, bool> comparer)
{
return first.Where(x => second.FirstOrDefault(y => comparer(x, y)) != null);
}
public static IEnumerable<TSource> Intersect<TSource, VSource>(this IEnumerable<TSource> first, IEnumerable<VSource> second, Func<TSource, VSource, bool> comparer)
{
return first.Where(x => second.Count(y => comparer(x, y)) == 1);
}
}
获取列表 A 中不在列表 b 中的所有元素:
var newData = ListA.Except(ListB, (a,b) => a.Family == b.Family);
备注:f.Brand != null ? f.Brand : null
等于f.Brand ?? null
等于f.Brand
如果您将更频繁地使用它来处理不同的 类,我的建议是为此创建一个通用扩展方法,这样您就可以像标准 LINQ 方法一样重用它。如果您不熟悉扩展方法,请阅读 Extension Methods Demystified。
所以我们必须输入不同类型的序列。序列 1 中的对象具有 属性 X,序列中的对象具有 属性 Y。您可以检查属性 X 和 Y 的值是否相等。
要求:return 序列 1 中的所有对象,其 属性 X 的值不等于序列 2 中对象的任何 Y 值。将此与副连接-相反。
所以我们先为一侧做一个程序。然后我们用 Concat
重用它,反之亦然
public static WhereNotMatched<Touter, Tinner, TKey>(
this IEnumerable<Touter> outer,
IEnumerable<Tinner> inner,
Func<Touter,TKey> outerKeySelector,
Func<TInner,TKey> innerKeySelector)
{
return WhereNotMatched(outer, inner, outerKeySelector, innerKeySelector, null);
{
public static IEnumerable<Touter> WhereNotMatched<Touter, Tinner, TKey>(
this IEnumerable<Touter> outer,
IEnumerable<Tinner> inner,
Func<Touter,TKey> outerKeySelector,
Func<TInner,TKey> innerKeySelector
IEqualityComparer<TKey> comparer)
{
// if no comparer provided, use the default comparer
if (comparer == null) comparer = EqualityComparer<TKey>.Default;
// TODO: check outer != null, inner != null, etc.
// extract all inner keys, for efficient lookup put them in a HashSet<TKey>
HashSet<TKey> innerKeys = new HashSet(inner.Select(i => innerKeySelector(i)), comparer);
// return all outer that have no corresponding value in the HashSet
return outer.Where(o => !innerKeys.Contains(innerKeySelector(o));
}
用法:
假设在一个订购系统中您有 Products、Orders 和 OrderLines。每个 OrderLine 都有一个外键 ProductId。此 ProductId 指的是此 OrderLine 中提到的产品。每个订单包含零个或多个订单行。
IEnumerable<Order> orders = ...
IEnumerable<Product> products = ...
// Get all Products that have never been ordered yet
IEnumerable<OrderLine> orderLines = orders.SelectMany(order => order.OrderLines);
IEnumerable<Product> neverOrderedProducts = products.WhereNotMatched(orderLines,
product => product.Id,
orderLine => orderLine.ProductId);
以下是您要的更多内容:
IEnumerable<Student> maleStudents = ...
IEnumerable<Student> femaleStudents = ...
假设每个学生都有 PromCompanion
。我们不是老式的,所以一些男性学生有一个不是女性学生的 PromCompanion,同样,一些女性学生有一个非男性学生作为 PromCompanion。找到所有这些学生。
IEnumerable<Student> result = maleStudents.WhereNotMatched(femaleStudents,
man => man.PromCompanion,
woman => woman.PromCompanion)
// concat with vice-versa
.Concat(femaleStudents.WhereNotMatched(maleStudents,
woman => woman.PromCompanion,
man => man.PromCompanion));
IEnumreable<Student> uncompaniedStudents = maleStudents.WhereNon