C# 从对象列表中删除重复项
我有一个域为:id,a,b,c,e,f的MyObject 我有一个包含500000个项目的列表,现在我如何删除所有重复的项目,这些项目的参数a,c,f值相同 我只寻找最快和最有效的方法 更新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
我实现了比较器 类中的字段类型不同,因此我使用
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
类的更多信息,请访问以下链接:
希望这对您有所帮助。您可以像这样使用LINQDistinct()
:
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();