C# 从对象列表中删除重复项

C# 从对象列表中删除重复项,c#,.net,arraylist,duplicates,C#,.net,Arraylist,Duplicates,我有一个域为:id,a,b,c,e,f的MyObject 我有一个包含500000个项目的列表,现在我如何删除所有重复的项目,这些项目的参数a,c,f值相同 我只寻找最快和最有效的方法 更新 我实现了比较器 类中的字段类型不同,因此我使用ToString()。这是个好办法吗? IdLoc,IdMet,Ser都很长吗? 值是对象 IdDataType很长 class Comparer : IEqualityComparer<MyObject> { public bool Equ

我有一个域为:id,a,b,c,e,f的MyObject 我有一个包含500000个项目的列表,现在我如何删除所有重复的项目,这些项目的参数a,c,f值相同

我只寻找最快和最有效的方法

更新
我实现了比较器

类中的字段类型不同,因此我使用
ToString()
。这是个好办法吗?
IdLoc
IdMet
Ser
都很长吗?
是对象
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();
    }
}
时间:0.35秒
但是返回的列表不在我的类中,为什么1和2的列表中的元素数量不同于3的列表

更新2

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秒

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


这将提供一个n log n speed解决方案,这可能是您能做的最好的解决方案。

如果您想要的是速度,并且不介意使用一些内存,那么我建议您使用
哈希集
,如果您有兴趣做一些自定义比较,那么您可以制作一个
IEqualityComparer
,大概是这样的:

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;
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.
var original=new ArrayList();//不管你最初的收藏是什么
var unique=new HasSet(new MyCustomEqualityComparer());
foreach(原始var项目)
{
如果(!unique.Contains(项目))
唯一。添加(项目);
}
返回唯一值;
这里的问题是,您最终可能会占用两倍于原始内存的内存

更新: 我做了一些额外的研究,我认为你可以通过简单地做以下事情来实现你想要的:

var original // your original data
var unique = new HashSet<YourClass>(origin, new CustomEqualityComparer());
var original//您的原始数据
var unique=new HashSet(origin,new CustomEqualityComparer());
这应该注意删除重复的数据,因为
哈希集中不允许重复。我建议您也看看关于
GetHasCode
的实施指南

如果您想了解有关
HashSet
类的更多信息,请访问以下链接:




希望这对您有所帮助。您可以像这样使用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();
    }
}
类比较器:IEqualityComparer
{
公共布尔等于(MyObject x,MyObject y)
{
返回x.a==y.a&&x.c==y.c&&x.f==y.f;
}
public int GetHashCode(MyObject obj)
{
返回(obj.a+obj.c+obj.f).GetHashCode();
}
}
德拉科! 您可以使用
Distinct()
方法仅获取具有不同属性值的值。
你可以这样做:

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;
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.
List List=新列表();
//运行将填充列表的代码。
var result=list.Select(myObj=>new{myObj.a、myObj.c、myObj.f})
.Distinct().ToList();
//结果包含基于差异的数据。

此链接中的代码对我来说非常有用。

公共类MyClass
{
公共字符串ID{get;set;}
公共字符串值{get;set;}
}
List myList=新列表();
var xrOptionSet=新的MyClass();
xrmoptionstart.ID=“1”;
xrOptionSet.Value=“100”;
var xroptionset1=新的MyClass();
xroptionset1.ID=“2”;
xroptionset1.Value=“200”;
var xroptionset2=新的MyClass();
xroptionset2.ID=“1”;
xroptionset2.Value=“100”;
myList.Add(xrmOptionSet);
myList.Add(xroptionset1);
myList.Add(xroptionset2);
//在这里,我们首先按标签对结果进行分组,然后从每组中选取第一项
var myDistinctList=myList.GroupBy(i=>i.ID)
.Select(g=>g.First()).ToList();

我建议您尝试一些代码,然后使用benchmarking.NET之类的基准库来查看它的性能。一旦您有了解决方案的基线,您就可以尝试其他方法,看看是否可以提高性能。不过,一般来说,最佳情况下的性能将受到所比较的参数类型和集合大小的限制。未排序的随机访问集合的最坏情况性能始终为O(n^2)。祝你好运,所有的东西都好吗?或者除了其中一个以外的所有选项?使用linq 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.
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();