2013-04-26 31 views
0

可以說我有一個自定義「Point」類的列表(我知道System.Drawing中有一個類,但可以說我需要一個自定義的類)。現在,這個名單有時可有相同點,因此,例如,說,這是建立這樣的:在列表中查找不同點(使用2個謂詞)

List<customPoint> myPoints = new List<customPoint>(); 
myPoints.Add(new customPoint(1,5)); 
myPoints.Add(new customPoint(1,5)); 
myPoints.Add(new customPoint(2,3)); 
myPoints.Add(new customPoint(4,9)); 
myPoints.Add(new customPoint(8,7)); 
myPoints.Add(new customPoint(2,3)); 

後來我需要做一些計算,但我不需要重複。這將是一個更優雅的方式做出的獨特點的新列表比這

List<customPoint> uniquePoints = new List<customPoint>(); 

for(int i; i < myPoints.Count; i++) 
{ 
    Boolean foundDuplicate = false;  

    int tempX = myPoints[i].X; 
    int tempY = myPoints[i].Y;   

    for(int j=0; j < uniquePoints.Count; j++) 
    { 
     if((tempX == uniquePoints[0].X) && (tempY == uniquePoints[0].Y)) 
     { 
      foundDuplicate = true; 
      break; 
     }    
    } 
    if(!foundDuplicate) 
    { 
     uniquePoints.Add(myPoints[i]); 
    }   
} 

我知道這是凌亂的,但,這就是爲什麼我問,如果有一個更優雅的方式。我查看了Linq的「Distinct」命令,但它看起來不起作用,我猜他們的對象實例化中有一些東西仍然是唯一的。

+0

您的'customPo int類(它應該是遵循命名約定的'CustomPoint')適當地覆蓋'Equals'和'GetHashCode'? – 2013-04-26 18:57:55

+0

這裏有一個鏈接[Distinct](http:// stackoverflow。com/questions/998066/linq-distinct-values)與前面的討論一起,連同指向msdn doc的鏈接截然不同 – user1376713 2013-04-26 18:57:16

回答

1

1)將這些方法你customPoint

public override int GetHashCode() 
{ 
    return X.GetHashCode() * 19 + Y.GetHashCode(); 
} 

public override bool Equals(object obj) 
{ 
    var other = obj as customPoint; 
    return this.X == other.X && this.Y == other.Y; 
} 

您可以使用LINQ的Distinct方法之後。

var distinctPoints = myPoints.Distinct().ToList(); 

2)可以使用匿名類型比較特技沒有覆蓋的任何方法。

var distinctPoints = myPoints.GroupBy(m => new { m.X, m.Y }) 
          .Select(x => x.First()) 
          .ToList(); 

3)你也可以做到這一點通過編寫自定義IEqualityComparer

public class MyEqualityComparer : IEqualityComparer<customPoint> 
{ 
    public bool Equals(customPoint a, customPoint b) 
    { 
     return a.X == b.X && a.Y == b.Y; 
    } 

    public int GetHashCode(customPoint other) 
    { 
     return other.X.GetHashCode() * 19 + other.Y.GetHashCode(); 
    } 
} 

var distinctPoints = myPoints.Distinct(new MyEqualityComparer()).ToList(); 
+0

我已經完成了Equals(但使用IEquatable),但沒有使用哈希碼。我也研究過GroupBy,但在理解類似的其他問題的語法方面遇到了一些麻煩。我對hashcode有點新,所以我很好奇,爲什麼在這種情況下X乘以19? – Xantham 2013-04-26 19:51:23

+1

@Xantham它是一個隨機素數,如果你寫了'return 0;',它甚至會工作。一個好的哈希算法可以提高性能。所有你必須確保的是,如果兩個對象相等,那麼它們的散列碼必須是相同的(但不一定是其他方法) – I4V 2013-04-26 20:20:02

+1

啊,這是有道理的。謝謝。 – Xantham 2013-04-26 20:21:34

1

你用什麼方法嘗試使用沒有工作的LINQ?下面的代碼應該這樣做:

var uniquePoints = myPoints.Distinct(); 
+1

我懷疑OP調用myPoints.Distinct()並忽略返回值。 – 2013-04-26 18:57:06

+0

啊,常見的錯誤。 – 2013-04-26 19:00:28

+0

或者他沒有正確覆蓋Equals/GetHashCode,當然:) – 2013-04-26 19:01:40

0

Distinct方法是一個很好的路要走,但爲了使用它,只要你願意,您必須在對象上實現EqualsGetHashCode,或創建IEqualityComparer<customPoint>並將其傳遞給Distinct方法。對於你的情況,在你的對象上實現這些方法可能是有意義的。從文檔:

默認的相等比較,Default,用於比較實現了IEquatable<T>泛型接口的類型 值。若要將 與自定義數據類型進行比較,則需要實現此接口並提供您自己的GetHashCodeEquals方法。

0

我LinqPad這樣做,所以藉口Dump() ...但這裏的實施方式您的customPoint等級:

void Main() 
{ 
    var myPoints = new List<customPoint>(); 
    myPoints.Add(new customPoint(1,5)); 
    myPoints.Add(new customPoint(1,5)); 
    myPoints.Add(new customPoint(2,3)); 
    myPoints.Add(new customPoint(4,9)); 
    myPoints.Add(new customPoint(8,7)); 
    myPoints.Add(new customPoint(2,3)); 

    myPoints.Distinct().Dump(); 
} 


public class customPoint { 
    public int X; 
    public int Y; 

    public customPoint(int x, int y){ 
     X = x; 
     Y = y; 
    } 

    public override Boolean Equals(Object rhs) { 
     var theObj = rhs as customPoint; 

     if(theObj==null) { 
      return false; 
     } else { 
      return theObj.X == this.X && theObj.Y == this.Y; 
     } 
    } 

    public override int GetHashCode() { 
     return X^Y; 
    } 
}