如何在集合中查找类似对象

Sta*_*tar 5 c# linq find

我想根据我实现方法在集合中找到类似的对象

例如这个示例类:

class myObj
{
    public int Data1 { get; set; }

    public int Data2 { get; set; }

    public int Data3 { get; set; }        
}
Run Code Online (Sandbox Code Playgroud)

然后在类中实现类似的方法:

public bool Similar(myObj obj)
{
    if (obj.Data1 == this.Data1 && obj.Data2 == this.Data2)
        return true;
    return false;
}
Run Code Online (Sandbox Code Playgroud)

现在我有这个集合:

List<myObj> items = new List<myObj>();
// none similar
items.Add(new myObj() { Data1 = 1, Data2 = 2, Data3 = 4 });
items.Add(new myObj() { Data1 = 2, Data2 = 3, Data3 = 18 });
items.Add(new myObj() { Data1 = 3, Data2 = 4, Data3 = 75 });
items.Add(new myObj() { Data1 = 4, Data2 = 2, Data3 = 3 });
//similar
items.Add(new myObj() { Data1 = 5, Data2 = 26, Data3 = 97 });
items.Add(new myObj() { Data1 = 5, Data2 = 26, Data3 = 37 });
items.Add(new myObj() { Data1 = 10, Data2 = 45, Data3 = 47 });
items.Add(new myObj() { Data1 = 10, Data2 = 45, Data3 = 19 });
Run Code Online (Sandbox Code Playgroud)

得到类似的对象,我这样做:

private static List<myObj> GetSimilars(List<myObj> items)
{
    List<myObj> similars = new List<myObj>();
    while (items.Count > 0)
    {
        var q = (from c in items
                 where c.Similar(items[0])
                 select c).ToList();

        if (q.Count > 1)
        {
            similars.AddRange(q);
            foreach (var obj in q)
                items.Remove(obj);
        }
        else
            items.Remove(items[0]);
    }    
    return similars;
}
Run Code Online (Sandbox Code Playgroud)

有没有更好的方法呢?

Jod*_*ell 2

制作这个可重用的类怎么样?

public class MyObjSimilarity : EqualityComparer<myObj>
{
    public override bool Equals(myObj a, myObj b)
    {
        if (obj.Data1 == this.Data1 && obj.Data2 == this.Data2)
        {
            return true;
        }

        return false;
    }

    public override int GetHashCode(myObj o)
    {
        int hash = 17;
        hash = hash * 23 + o.Data1.GetHashCode();
        hash = hash * 23 + o.Data2.GetHashCode();
        return hash;
    }
}
Run Code Online (Sandbox Code Playgroud)

你可以这样使用,

var similarity = new MyObjSimilarity();
items.Where(o => similarity.Equals(o, w));
Run Code Online (Sandbox Code Playgroud)

或传递到字典的构造函数中,

var similarity = new MyObjSimilarity();
var lookup = new Dictionary<myObj, string>(similarity);
Run Code Online (Sandbox Code Playgroud)

或在一个GroupBy

var similarity = new MyObjSimilarity();
items.GroupBy(o => o, o => o, similarity);
Run Code Online (Sandbox Code Playgroud)

或者喜欢其他答案

var similarity = new MyObjSimilarity();
items.GroupBy(
    o => o,
    o => new { Instance = o, Count = Count(o) },
    similarity);
Run Code Online (Sandbox Code Playgroud)

或者在其他框架友好的地方。