2017-10-08 55 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); 
    } 
} 
相關問題