C# 在列表中查找不同的点(使用2个谓词)
假设我有一个自定义“点”类的列表(我知道System.Drawing中有一个,但假设我需要一个自定义类)。现在这个列表有时可能有相同的点,例如,假设它是这样设置的:C# 在列表中查找不同的点(使用2个谓词),c#,linq,duplicates,C#,Linq,Duplicates,假设我有一个自定义“点”类的列表(我知道System.Drawing中有一个,但假设我需要一个自定义类)。现在这个列表有时可能有相同的点,例如,假设它是这样设置的: List<customPoint> myPoints = new List<customPoint>(); myPoints.Add(new customPoint(1,5)); myPoints.Add(new customPoint(1,5)); myPoints.Add(new customPoint(
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 myPoints=new List();
添加(新的customPoint(1,5));
添加(新的customPoint(1,5));
添加(新的customPoint(2,3));
添加(新的customPoint(4,9));
添加(新的customPoint(8,7));
添加(新的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]);
}
}
List uniquePoints=new List();
for(int i;i
我知道这很混乱,但这就是为什么我问是否有更优雅的方式。我查看了Linq“Distinct”命令,但它似乎不起作用,我想在它们的对象实例化中仍然有一些独特的地方。您尝试使用Linq做了哪些不起作用的事情?下面的代码应该可以做到这一点:
var uniquePoints = myPoints.Distinct();
该方法将是一个很好的方法,但为了按您的意愿使用它,您必须在对象上实现Equals
和GetHashCode
,或者创建一个IEqualityComparer
并将其传递到Distinct
方法中。对于您的情况,在对象上实现这些方法可能是有意义的。从文件中:
默认的相等比较器用于比较
实现泛型接口的类型。到
比较自定义数据类型,您需要实现此接口和
提供您自己的类型和方法
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();
公共类MyEqualityComparer:IEqualityComparer
{
公共布尔等于(自定义点a、自定义点b)
{
返回a.X==b.X&&a.Y==b.Y;
}
public int GetHashCode(customPoint其他)
{
返回other.X.GetHashCode()*19+other.Y.GetHashCode();
}
}
var distinctPoints=myPoints.Distinct(新的MyEqualityComparer()).ToList();
我是在LinqPad中这样做的,所以请原谅转储()
…但是这里有一种方法可以实现您的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;
}
}
void Main()
{
var myPoints=新列表();
添加(新的customPoint(1,5));
添加(新的customPoint(1,5));
添加(新的customPoint(2,3));
添加(新的customPoint(4,9));
添加(新的customPoint(8,7));
添加(新的customPoint(2,3));
myPoints.Distinct().Dump();
}
公共类海关关卡{
公共int X;
公共智力;
公共自定义点(整数x,整数y){
X=X;
Y=Y;
}
公共覆盖布尔等于(对象rhs){
var theObj=rhs作为自定义点;
if(theObj==null){
返回false;
}否则{
返回theObj.X==this.X&&theObj.Y==this.Y;
}
}
公共覆盖int GetHashCode(){
返回X^Y;
}
}
我怀疑OP调用了myPoints.Distinct()
并忽略了返回值。或者他没有正确地覆盖Equals/GetHashCode,当然:)@JonSkeet确实如此,至少在GetHashCode上,我不知道我可以覆盖它,直到我问了这个问题。我按照阿贝·米斯勒的建议做了,但没有凌驾于那些建议之上,这是行不通的。你如何生成一个散列,这样就不太可能得到不同的点,并且有唯一的代码,特别是当我比较(2,1)和(1,2)时?这里有一个到前面讨论的链接,以及到distinctDoes yourcustomPoint
类上msdn文档的链接(哪一个应该是CustomPoint
以遵循命名约定)适当地覆盖Equals
和GetHashCode
?我已经完成了Equals(但使用了IEquatable),但不是散列码。我也研究过GroupBy,但在理解以类似方式使用它的其他问题的语法时有点困难。我对散列码有点陌生,所以我很好奇,为什么在这种情况下X乘以19?@xantam这是一个随机素数,如果你写返回0; 。一个好的散列算法可能会提高性能,仅此而已。您需要确保的是,如果两个对象相等,则它们的散列码必须相同。(但不一定相反)啊,这很有意义。谢谢。