我有一个包含三个值的类
public class hitOBject {
public string v1;
public float v2;
public float v3;
}
我在运行时动态创建这些对象,这些对象存储在自己的列表中。
List<hitOBject> Detected = new List<hitOBject>();
但是,当一个新对象添加到此列表时,我首先需要检查是否已存在包含重复值的列表。 例如......
如果我有2个hitObjects
obj1 obj2
v1 = bob v1 = bob
v2 = 1f v2 = 3f
v3 = 2.5f v3 = 3.5f
如果我想检查列表中是否已存在V1,是否有方法可以执行此操作?
我知道如果它是一个重复的对象我可以执行以下代码吗?
if(!Detected.Contains(object))
但是当我在寻找一个子值时,这不起作用?
有人能指出我正确的方向吗?
答案 0 :(得分:1)
if(!Detected.Any(o1 => o1.v1 == o2.v1 && o1.v2 == o2.v2 && o1.v3 == o2v3))
请遵循C#惯例。变量(Detected)应该是camelCase,类(hitObject)应该是PascalCase
如果列表很大(超过50个元素),请考虑使用HashSet作为@Servy建议
答案 1 :(得分:1)
覆盖GetHashCode
和Equals
。如果您要与班级中的单个字段/属性进行比较,请仅指定该字段:
public class hitOBject
{
public string v1;
public float v2;
public float v3;
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return ((hitOBject)obj).v1 == this.v1;
}
public override int GetHashCode()
{
return (v1 != null ? v1.GetHashCode() : 0);
}
}
然后你可以使用:
List<hitOBject> Detected = new List<hitOBject>();
Detected.Add(new hitOBject {v1 = "bob", v2 = 1f, v3 = 2.5f});
hitOBject secondObject = new hitOBject {v1 = "bob", v2 = 1f, v3 = 2.5f};
if (Detected.Contains(secondObject))
{
Console.WriteLine("Alread Exists");
}
由于List<T>.Contains
使用Equals
来比较相等性,因此覆盖Equals
方法将根据字段v1
的比较返回bool。
如果您要在List
中拥有唯一值,那么最好使用HashSet<T>
,因为它只允许基于GetHashCode
和Equals
实施的唯一值。
HashSet<hitOBject> Detected = new HashSet<hitOBject>();
Detected.Add(new hitOBject {v1 = "bob", v2 = 1f, v3 = 2.5f});
hitOBject secondObject = new hitOBject {v1 = "bob", v2 = 1f, v3 = 2.5f};
Detected.Add(secondObject);
在上面的代码中,最后,您的HashSet
只会包含一个项目,而secondObject
将不会添加到HashSet
。
如果您不想覆盖GetHashCode
和Equals
,则可以使用LINQ查询来确定列表中是否存在对象,如:
hitOBject secondObject = new hitOBject {v1 = "bob", v2 = 1f, v3 = 2.5f};
if (Detected.Any(r => r.v1 == secondObject.v1))
{
//Already exists
}
另一种选择是让您的课程保持原样并实施IEqualityComparer<T>
,如
private sealed class hitObjectV1EqualityComparer : IEqualityComparer<hitOBject>
{
public bool Equals(hitOBject x, hitOBject y)
{
if (ReferenceEquals(x, y)) return true;
if (ReferenceEquals(x, null)) return false;
if (ReferenceEquals(y, null)) return false;
if (x.GetType() != y.GetType()) return false;
return string.Equals(x.v1, y.v1);
}
public int GetHashCode(hitOBject obj)
{
return (obj.v1 != null ? obj.v1.GetHashCode() : 0);
}
}
然后你可以在HashSet<T>
构造函数中传递它,如:
另见:General Naming Conventions C# - MSDN
HashSet<hitOBject> Detected = new HashSet<hitOBject>(new hitObjectV1EqualityComparer());
稍后添加项目
Detected.Add(new hitOBject {v1 = "bob", v2 = 1f, v3 = 2.5f});
hitOBject secondObject = new hitOBject {v1 = "bob", v2 = 1f, v3 = 2.5f};
Detected.Add(secondObject);
您最终会在HashSet
中找到一个项目。
您可以将该Comparer与List<T>.Contains
一起使用,如:
List<hitOBject> Detected = new List<hitOBject>();
var MyEqualityComparer = new hitObjectV1EqualityComparer();
Detected.Add(new hitOBject {v1 = "bob", v2 = 1f, v3 = 2.5f});
hitOBject secondObject = new hitOBject {v1 = "bob", v2 = 1f, v3 = 2.5f};
if (Detected.Contains(secondObject, MyEqualityComparer))
{
//Already Exists
}
else
{
Detected.Add(secondObject);
}
答案 2 :(得分:0)
任何函数都是LINQ并查找任何匹配项;如果没有任何匹配,那么添加到列表...是你需要的吗?
if (!Detected.Any(Function(i) i.V1 = obj2.V1))
Detected.Add(obj2);
只需添加以获得LINQ支持:
using System.Linq;
答案 3 :(得分:0)
在HitObject
:
IEquatable<T>
interface
public class HitObject : IEquatable<HitObject>
{
public string V1;
public float V2;
public float V3;
public bool Equals(HitObject other)
{
return this.V1 == other.V1;
}
}
然后您可以使用Contains
方法:
List<HitObject> detected = new List<HitObject>();
detected.Add(new HitObject
{
V1 = "bob",
V2 = 1f,
V3 = 2.5f
});
HitObject something = new HitObject
{
V1 = "bob",
V2 = 3f,
V3 = 3.5f
};
if (!detected.Contains(something))
{
// this line will not be executed
detected.Add(something);
}