检查c#对象列表是否包含具有相同变量的对象。

时间:2014-10-22 19:30:20

标签: c#

我有一个包含三个值的类

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))

但是当我在寻找一个子值时,这不起作用?

有人能指出我正确的方向吗?

4 个答案:

答案 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)

覆盖GetHashCodeEquals。如果您要与班级中的单个字段/属性进行比较,请仅指定该字段:

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>,因为它只允许基于GetHashCodeEquals实施的唯一值。

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

如果您不想覆盖GetHashCodeEquals,则可以使用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

中实施the 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);
}