2017-10-08 31 views
0

我有一个类,我用它来描述一个XYZ坐标以及3个属性。类与如果在一个属性上相等

类看起来是这样的:

class dwePoint 
{ 
     public double X { get; set; } 
     public double Y { get; set; } 
     public double Z { get; set; } 
     public string Prop1 { get; set; } 
     public string Prop2 { get; set; } 
     public string Prop3 { get; set; } 

     public override bool Equals(object obj) 
     { 
      return Equals(obj as dwePoint); 
     } 

     protected bool Equals(dwePoint other) 
     { //This doesnt seem to work 
      if(Prop1== "Keep") 
      { 
       return false; 
      } 
      return X.Equals(other.X) && Y.Equals(other.Y) && Z.Equals(other.Z); 
     } 

     public override int GetHashCode() 
     { 
      unchecked 
      { 
       var hashCode = X.GetHashCode(); 
       hashCode = (hashCode * 397)^Y.GetHashCode(); 
       hashCode = (hashCode * 397)^Prop1.GetHashCode(); 
       hashCode = (hashCode * 397)^Z.GetHashCode(); 
       return hashCode; 
      } 
     } 
} 

Equals检查XYZ,我可以过滤掉仅根据实际坐标重复,忽视了性能。 在我的代码,我使用了一个列表,所以我称之为List.Distinct()

现在有一件事我找不出尚未: 有2点与同XYZ这是可能的,但具有不同的属性。 在这种情况下,我总是希望保留一个特定的字符串(例如“Keep”),并始终删除具有其他值的那个。

我已经尝试了一些if声明,没有任何运气...

我应该如何处理呢?

+1

*我已经在尝试一些if语句*。你能表演吗? –

+0

@ S.Akbari编辑我的文章;我的逻辑是有可能是2点(或更多)与相同的XYZ,其中只有2中的1有“保持”在Prop1;因此那一个会是错误的,但是检查其他人应该将它作为一个副本返回。 –

+0

如果您将一个对象与'Prop1 =='Keep'与自身进行比较,这会产生'false',这显然是错误的。 –

回答

1

你想要的不是Distinct,因为它使用你的Equals,因为它只是平等的输入(因为它应该),所以它没有办法知道对象之间可能有区别。

我认为这会是一个更好的设计,让你用一个新的课程组成你的课堂,例如,包含您的坐标和您的3个属性的Point3D。然后,你可以按照这个观点进行分组,并且对于有多个相同点的事物,根据你自己的逻辑来确定要保留的内容。

在代码:

class Point3D 
{ 
    public double X { get; set; } 
    public double Y { get; set; } 
    public double Z { get; set; } 
    // Equals and get hash code here 
} 

class dwePoint 
{ 
    Point3D Coordinate {get;} 
    public string Prop1 { get; set; } 
    public string Prop2 { get; set; } 
    public string Prop3 { get; set; } 
} 

// Filter list by applying grouping and your custom logic 
points = points.GroupBy(p => p.Coordinate) 
    .Select(x => 
     x.OrderByDescending(p => p.Prop1 == "Keep") // Sort so the element you want to keep is first 
     .First()         // If there is only one element, the ordering will not matter 
    ).ToList(); 

如果你真的想要,在GroupBy还与当前类的设计,因为只有坐标参与的Equals

+0

感谢您的完善和代码示例。必须多读几遍才能完全理解,但它对我有很大的帮助(我没有专业的编码背景) –

+0

我已经掌握了它,现在已经非常了解它了。 只有1件事我不知道。我可以指定我自定义的字符串优先顺序吗?所以第一个选择将是“保持”第二个“SomeName”第三个“SomethingElse”等。 –

-1

我和driis提供了相同的答案.. 但是,我想为您提供另一种选择。

你可以自己写一个Distinct作为扩展方法。 这是一个解决方法。我写了一个示例代码,以便您可以更好地理解。

static class Program 
{ 
    static void Main(string[] args) 
    { 
     List<Abc> list = new List<Abc>() 
     { 
      new Abc() 
      { 
       a = 5, 
       b = 6, 
       s = "Phew" 
      }, 
      new Abc() 
      { 
       a = 9, 
       b = 10, 
       s = "Phew" 
      }, 
      new Abc() 
      { 
       a = 5, 
       b = 6, 
       s = "Keep" 
      }, 
      new Abc() 
      { 
       a = 9, 
       b = 10, 
       s = "Keep" 
      }, 
      new Abc() 
      { 
       a = 5, 
       b = 6, 
       s = "Phew" 
      }, 
      new Abc() 
      { 
       a = 9, 
       b = 10, 
       s = "Phew" 
      }, 
     }; 
     list = list.MyDistinct(); 
    } 

    // Extension Method 
    public static List<Abc> MyDistinct(this List<Abc> list) 
    { 
     List<Abc> newList = new List<Abc>(); 
     foreach (Abc item in list) 
     { 
      Abc found = newList.FirstOrDefault(x => x.Equals(item)); 
      if (found == null) 
      { 
       newList.Add(item); 
      } 
      else 
      { 
       if (found.s != "Keep" && item.s == "Keep") 
       { 
        newList.Remove(found); 
        newList.Add(item); 
       } 
      } 
     } 
     return newList; 
    } 
} 

class Abc 
{ 
    public int a, b; 
    public string s; 

    public override bool Equals(object obj) 
    { 
     Abc other = obj as Abc; 
     return a == other.a && b == other.b; 
    } 

    public override int GetHashCode() 
    { 
     return a.GetHashCode()^b.GetHashCode(); 
    } 
} 

希望它会帮助你..

0

你的GetHashCode跑入nullref如果PROP1 == NULL,你应该解决这个问题。

而另一种解决方案:使用Aggregate和Lamda来区分您的列表。你的类上的Equal()只比较X,Y和Z--聚合lambda确保你保持你想要的。可能将聚合放入扩展方法或函数中。

static void Main() 
{ 
    List<dwePoint> points = new List<dwePoint>(); 
    // Testdata 
    for (int x = 0; x < 3; x++) 
     for (int y = 0; y < 3; y++) 
      for (int z = 0; z < 3; z++) 
      { 
       points.Add(new dwePoint { X = x, Y = y, Z = z }); 
       if (x == y && x == z) // and some duplicates to Keep 
        points.Add(new dwePoint { X = x, Y = y, Z = z, Prop1 = "Keep" }); 
      } 

    // prefer the ones with "Keep" in Prop1 
    var distincts = points.Aggregate(new HashSet<dwePoint>(), (acc, p) => 
    { 
     if (acc.Contains(p)) 
     { 
      var oldP = acc.First(point => point.X == p.X && point.Y == p.Y && point.Z == p.Z); 
      if (oldP.Prop1 == "Keep") 
      { 
       // do nothing - error, second point with "keep" 
      } 
      else 
      { 
       acc.Remove(oldP); 
       acc.Add(p); // to use this ones other props later on .... 
      } 
     } 
     else 
      acc.Add(p); 

     return acc; 
    }).ToList(); 

    Console.WriteLine(string.Join(" - ", points)); 
    Console.WriteLine(string.Join(" - ", distincts)); 
    Console.ReadLine(); 
} 


private class dwePoint 
{ 
    public string Prop1 { get; set; } 
    public string Prop2 { get; set; } 
    public string Prop3 { get; set; } 
    public double X { get; set; } 
    public double Y { get; set; } 
    public double Z { get; set; } 

    public override bool Equals(object obj) 
    { 
     return Equals(obj as dwePoint); 
    } 

    public override int GetHashCode() 
    { 
     unchecked 
     { 
      var hashCode = X.GetHashCode(); 
      hashCode = (hashCode * 397)^Y.GetHashCode(); 
      hashCode = (hashCode * 397)^Z.GetHashCode(); 
      return hashCode; 
     } 
    } 

    public override string ToString() => $"{X}-{Y}-{Z}-{Prop1}-{Prop2}-{Prop3}"; 

    protected bool Equals(dwePoint other) 
    { 
     return X.Equals(other.X) && Y.Equals(other.Y) && Z.Equals(other.Z); 
    } 
} 
相关问题