繁体   English   中英

从对象列表中删除重复项

[英]Remove duplicates from list of object

我有MyObject,其字段为:id,a,b,c,e,f,并且我有500 000个项目的List,现在如何删除参数a,c,f具有相同值的所有重复项目?

我只在寻找最快,最有效的方法。

UPDATE
我实现了比较器

类中的字段具有不同的类型,因此我使用ToString() 这是好方法吗?
IdLocIdMetSer很长?
Value就是对象
IdDataType很长

class Comparer : IEqualityComparer<MyObject>
{
    public bool Equals(MyObject x, MyObject y)
    {                
        return x.IdLoc == y.IdLoc && x.IdMet == y.IdMet && x.Ser == y.Ser &&
               x.IdDataType == y.IdDataType && x.Time == y.Time && x.Value == y.Value;
    }

    public int GetHashCode(MyObject obj)
    {
        string idLoc = obj.IdLoc.HasValue ? obj.IdLoc.ToString() : String.Empty;
        string idMet = obj.IdMet.HasValue ? obj.IdMet.ToString() : String.Empty;
        string ser = obj.Ser.HasValue ? obj.Ser.ToString() : String.Empty;
        string value = obj.Value != null ?  obj.Value.ToString() : String.Empty;

        return (idLoc + idMet + ser + value + obj.IdDataType.ToString() + obj.Time.ToString()).GetHashCode();
    }
}

删除重复项
元素566890
1)时间:2秒

DateTime start = DateTime.Now;
List<MyObject> removed = retValTmp.Distinct(new Comparer()).ToList();
double sec = Math.Round((DateTime.Now - start).TotalSeconds, 3);

2)时间:1.5秒

start = DateTime.Now;
List<MyObject> retList = new List<MyObject>();
HashSet<MyObject> removed2 = new HashSet<MyObject>(new Comparer());
foreach (var item in retValTmp)
{
    if (!removed2.Contains(item))
    {
        removed2.Add(item);
        retList.Add(item);
    }
}                
double sec2 = Math.Round((DateTime.Now - start).TotalSeconds, 3);

4)我也尝试过这种方式:

start = DateTime.Now;

var removed3 = retValTmp.Select(myObj => new { myObj.IdLoc, myObj.IdMet, myObj.Ser, myObj.Value, myObj.IdDataType, myObj.Time }).Distinct().ToList();

double sec3 = Math.Round((DateTime.Now - start).TotalSeconds, 3);

时间:0.35秒
但是返回的列表不在我的课程中,为什么列表1和2中的元素数与列表3中的元素数不同?

UPDATE2

public int GetDataHashCode(MyObject obj)
{
    long idLoc = obj.IdLoc.HasValue ? obj.IdLoc.Value : 0;
    long idMet = obj.IdMet.HasValue ? obj.IdMet.Value : 0;
    long ser = obj.SerHasValue ? obj.Ser.Value : 0;
    int valueHash = 0;
    if (obj.Value != null)
        valueHash = obj.Value.GetHashCode();
    else
        valueHash = valueHash.GetHashCode();

    return (idLoc.GetHashCode() + idMet.GetHashCode() + ser.GetHashCode() + valueHash  + obj.IdDataType.GetHashCode() + obj.Time.GetHashCode()).GetHashCode();
}

采用:

foreach (MyObject daItem in retValTmp)
{
    int key = GetDataHashCode(daItem);
    if (!clearDict.ContainsKey(key))
        clearDict.Add(key, daItem);
} 

元素:750000
时间: 0.23秒!

如果您正在寻找的是速度,并且不介意占用一些内存,那么我建议您使用HashSet ,如果您有兴趣进行一些自定义比较,则可以制作IEqualityComparer<T> ,例如这个:

var original = new ArrayList(); // whatever your original collection is 
var unique = new HasSet<YourClass>(new MyCustomEqualityComparer());

foreach(var item in original)
{
    if(!unique.Contains(item))
        unique.Add(item);
}

return unique;

这里的问题是,您最终可能会吞噬原始内存的两倍。

更新:

我进行了一些额外的研究,我认为您只需做以下即可达到您想要的目标:

var original // your original data
var unique = new HashSet<YourClass>(origin, new CustomEqualityComparer());

应该注意删除重复的数据,因为HashSet不允许重复。 我建议你也看看这个问题,大约GetHasCode实施准则。

如果您想进一步了解HashSet类,请遵循以下链接:

关于HashSet
关于IEqualityComparer构造函数
IEqualityComparer文档

希望这可以帮助

一种有效的方法是,首先基于(a,c,f)的哈希表进行快速排序(或类似的n Log n排序),然后可以遍历结果列表,每次(a)的值都选择一个,c,f)更改。

这将提供一个log n速度解决方案,这可能是您可以做的最好的事情。

好吧,您始终可以像这样使用LINQ Distinct()

var matches = list.Distinct(new Comparer()).ToList();

但是Ditsinct()正常工作,您需要为您的类实现Comparer:

class Comparer : IEqualityComparer<MyObject>
{
    public bool Equals(MyObject x, MyObject y)
    {
        return x.a == y.a && x.c == y.c && x.f == y.f;
    }

    public int GetHashCode(MyObject obj)
    {
        return (obj.a + obj.c + obj.f).GetHashCode();
    }
}

Drakko! 您可以使用Distinct()方法仅获取具有与您指定的属性不同的值的值。
您可以执行以下操作:

List<MyObj> list = new List<MyObj>();

//Run the code that is going to populate your list.
var result = list.Select(myObj => new { myObj.a, myObj.c, myObj.f})
                 .Distinct().ToList();

//Result contains the data based on the difference.

此链接中的代码对我来说很棒。 https://nishantrana.me/2014/08/14/remove-duplicate-objects-in-list-in-c/

public class MyClass
{
public string ID { get; set; }
public string Value { get; set; }

}

List<MyClass> myList = new List<MyClass>();
var xrmOptionSet = new MyClass();
xrmOptionSet.ID = "1";
xrmOptionSet.Value = "100";
var xrmOptionSet1 = new MyClass();
xrmOptionSet1.ID = "2";
xrmOptionSet1.Value = "200";
var xrmOptionSet2 = new MyClass();
xrmOptionSet2.ID = "1";
xrmOptionSet2.Value = "100";
myList.Add(xrmOptionSet);
myList.Add(xrmOptionSet1);
myList.Add(xrmOptionSet2);

// here we are first grouping the result by label and then picking the first item from each group
var myDistinctList = myList.GroupBy(i => i.ID)
.Select(g => g.First()).ToList();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM