添加没有重复的列表列表

时间:2018-05-21 11:40:52

标签: c# linq

我正在尝试合并两个嵌套列表。我有一个LatLng类,它包含两个属性,纬度和经度 - 两者都是双打。这个类是从名为DotNetCoords的NuGet包中引入的。一条线表示为LatLngs数组,我在网络中有一个数字行,如下所示:

IEnumerable<LatLng[]> lineNetwork; 

我想要添加另一个网络线,但是我要尝试区分重复,但我不认为LatLng是等同的,所以这似乎不起作用。

我也尝试过以下无法解决的问题。

IEnumerable<LatLng[]> lineNetwork; 
IEnumerable<LatLng[]> newLineNetwork;  

lineNetwork.AddRange(newLineNetwork.Where(x => !lineNetwork.Contains(x)));

在添加之前,需要检查行中的所有坐标是否相等。例如:

LatLng[] line1 = { 
new LatLng(Latitude: 0.1, Longitude: 0.1),
new LatLng(Latitude: 0.2, Longitude: 0.2),
new LatLng(Latitude: 0.3, Longitude: 0.3)
}
LatLng[] line2 = { 
new LatLng(Latitude: 0.1, Longitude: 0.1),
new LatLng(Latitude: 0.2, Longitude: 0.2),
new LatLng(Latitude: 0.3, Longitude: 0.3)
}
LatLng[] line3 = { 
new LatLng(Latitude: 0.1, Longitude: 0.1),
new LatLng(Latitude: 0.4, Longitude: 0.4),
new LatLng(Latitude: 0.5, Longitude: 0.5)
}

Line1&amp;将添加Line3,但不会添加Line2,因为所有坐标都与Line1共享。

2 个答案:

答案 0 :(得分:2)

一种方法是实施IEqualityComparer,以便比较LatLng的两个实例,而不是使用IEnumerabe<T>.Distinct。但是,由于您拥有该类型的数组,您还需要比较器来处理该数组类型:

class MyComparer : IEqualityComparer<LatLng[]>
{
    public bool Equals(LatLng[] x, LatLng[y])
    {
        return a.SequenceEquals(y, new MyLatLngComparer(0.001));
    }
    public int GetHashCode(LatLng[] x)
    {
        return x.First().GetHashCode();
    }
}

由于LatLng - 类没有自己的相等实现,因此您必须在SequenceEquals内提供自己的实现:

class MyLatLngComparer : IEqualityComparer<LatLng>
{
    private readonly double Tolerance;
    public MyLatLngComparer(double tolerance) { this.Tolerance = tolerance ;}
    public bool Equals(LatLng x, LatLng y)
    {
        return Math.Abs(x - y) <= Tolerance;
    }
    public int GetHashCode(LatLng x)
    {
        return x.GetHashCode();
    }
}

在这里,您将看到如何比较浮点值。如上所示,这些类型的平等应该通过一些小容忍来实现,以避免舍入问题。

最后,您可以将Distinct与提供的比较器一起使用:

lineNetwork.AddRange(newLineNetwork.Distinct(new MyComparer()));

为简洁起见,我也省略了一些空检查。你应该特别检查你的阵列是否有一个元素,例如在MyComparer.GetHashCode内。

答案 1 :(得分:-1)

三种可能的选择:

  1. 扩展LatLng并覆盖Equals和GetHashCode
  2. 如前所述实施IEquatable<LatLng>(类似于上一个选项,但效率更高)
  3. 使用您显示的linq代码,但添加扩展方法以实现Contains操作(您的代码失败,因为Contains尝试根据对象引用搜索相等性。唯一的方法是覆盖Equals方法)