如何从嵌套对象列表中删除重复项?

How to remove duplicates from a list of nested objects?

我知道有很多答案建议覆盖 equals 和 hashcode,但就我而言,这是不可能的,因为所使用的对象是从 DLL 导入的。

首先,我有一个名为 DeploymentData 的对象列表。

这些对象以及其他属性包含以下两个:Location(double x, double y, double z)Duct(int id)

目标是删除具有相同 Location 参数的那些。

首先,我按 Duct 对它们进行分组,因为 Location 如果在另一个管道上则不能相同。

var groupingByDuct = deploymentDataList.GroupBy(x => x.Duct.Id).ToList();

那么实际的算法:

List<DeploymentData> uniqueDeploymentData = new List<DeploymentData>();
foreach (var group in groupingByDuct) {
   uniqueDeploymentData 
      .AddRange(group 
      .Select(x => x)
      .GroupBy(d => new { d.Location.X, d.Location.Y, d.Location.Z })
      .Select(x => x.First()).ToList());
}

这确实有效,但为了正确检查它们是否确实重复,应该比较整个位置。为此,我做了以下方法:

private bool CompareXYZ(XYZ point1, XYZ point2, double tolerance = 10)
{
   if (System.Math.Abs(point1.X - point2.X) < tolerance &&
       System.Math.Abs(point1.Y - point2.Y) < tolerance &&
       System.Math.Abs(point1.Z - point2.Z) < tolerance) {
      return true;
   }
   return false;
}

但是 我不知道如何将它应用到上面编写的代码中。总结:

过滤重复项的一种简单方法是使用具有自定义相等比较器的哈希集。这是实现 IEqualityComparer 的 class,例如:

public class DeploymentDataEqualityComparer : IEqualityComparer<DeploymentData>
{
  private readonly double _tolerance;

  public DeploymentDataEqualityComparer(double tolerance)
  {
    _tolerance = tolerance;
  }

  public bool Equals(DeploymentData a, DeploymentData b)
  {
    if (a.Duct.id != b.Duct.id)
      return false; // Different Duct, therefore not equal
    if (System.Math.Abs(a.Location.X - b.Location.X) < _tolerance &&
       System.Math.Abs(a.Location.Y - b.Location.Y) < _tolerance &&
       System.Math.Abs(a.Location.Z - b.Location.Z) < _tolerance) {
      return true;
     }
     return false;
  }

  public GetHashCode(DeploymentData dd)
  {
    // If the classes of the library do not implement GetHashCode, you can create a custom implementation
    return dd.Duct.GetHashCode() | dd.Location.GetHashCode();
  }
}

为了过滤重复项,您可以将它们添加到 HashSet 中:

var hashSet = new HashSet<DeploymentData>(new DeploymentDataEqualityComparer(10));
foreach (var deploymentData in deploymentDataList)
  hashSet.Add(deploymentData);

这样就不需要通过管道分组,也不需要使用HashSet的增强性能。