提问人:Blake Rivell 提问时间:1/10/2023 最后编辑:M. JustinBlake Rivell 更新时间:11/3/2023 访问量:82
在 c 中使用 linq intersect 和 equality 将多个列表合并为一个不同的列表#
Combining several lists into a single distinct list using linq intersect and equality in c#
问:
我需要使用 linq 和 intersect 将多个列表合并为一个 combinedDistinct 列表。我最终得到一个空列表。知道我可能做错了什么吗?
这是我的代码:
合并所有不同的材料项目
List<Material> combinedMaterialList = new List<Material>();
foreach (var project in projects)
{
combinedMaterialList = combinedMaterialList.Intersect(project.Materials).ToList();
}
这是 Material 类,因为 intersect 将基于 Equality 工作:
public int Id { get; set; }
public int ExternalId { get; set; }
public string? Name { get; set; }
public decimal Quantity { get; set; }
public bool Equals(Material m)
{
if (m is null)
{
return false;
}
// Optimization for a common success case.
if (Object.ReferenceEquals(this, m))
{
return true;
}
// If run-time types are not exactly the same, return false.
if (this.GetType() != m.GetType())
{
return false;
}
// Return true if the fields match.
// Note that the base class is not invoked because it is
// System.Object, which defines Equals as reference equality.
return (ExternalId == m.ExternalId);
}
public override int GetHashCode()
{
return HashCode.Combine(Id, ExternalId, Name, Quantity);
}
答:
1赞
Dmitry Bychenko
1/10/2023
#1
首先,请确保你已经实现了 和 对于类:Equals
GetHashCode
Material
public class Material: IEquatable<Material> {
...
public bool Equals(Material other) {
if (ReferenceEquals(this, other))
return true;
if (other is null)
return false;
return ExternalId == other.ExternalId;
}
public override bool Equals(object o) => o is Material other && Equals(other);
// Note, that GetHashCode must not be more restrictive than Equals:
// If Equals compare ExternalId only, so must do GetHashCode
public override int GetHashCode() => ExternalId;
}
实施后,您应该选择以下方法之一:Equals
Intersect
:两个列表中的所有项目Union
:至少一个列表中的所有项目Except
:第一个列表中的所有项目,但不在第二个列表中
在任何情况下,重复项都将被删除。
例如:
// Since combinedMaterialList is empty,
// Intersect or Except have no meaning here: the result will be
// an empty list. The only reasonable choice is Union
List<Material> combinedMaterialList = new List<Material>();
// Combined list contains item from all project.Materials,
// duplicates removed
foreach (var project in projects) {
combinedMaterialList = combinedMaterialList
.Union(project.Materials)
.ToList();
}
评论
Material
IEquatable<Material>
Equals(object)
IEqualityComparer
IEqualityComparer
Intersect
IEquatable<T>
IEqualityComparer<T>
StringComparer