C# 确保列表中的每个项目都是唯一的?
假设我有一个1到10.000.000项的列表。类型为列表。CustomObj如下所示:C# 确保列表中的每个项目都是唯一的?,c#,list,filter,unique,hashset,C#,List,Filter,Unique,Hashset,假设我有一个1到10.000.000项的列表。类型为列表。CustomObj如下所示: class Person { public string Prename; public string Lastname; public CustomObj(string pre, string last) { Prename = pre; Lastname = last; } } HashSet<Person> hsPerson =
class Person
{
public string Prename;
public string Lastname;
public CustomObj(string pre, string last)
{
Prename = pre;
Lastname = last;
}
}
HashSet<Person> hsPerson = new HashSet<Person>(myExistingList);
public void Add(Person person)
{
if (!_list.Any(p => p.Prename == person.PreName && p.Lastname == person.Lastname))
{
_list.Add(person);
}
}
我想确定的是,名单上的每个人都是独一无二的。因此,如果我尝试添加一个“Tim Stone”,而列表中已经有一个“Tim Stone”,那么新的一个将不会被添加或过滤掉
我尝试使用List.Distinct()函数删除重复项。遗憾的是,它对自定义对象的效果不太好,我最终得到了重复的对象
哈希集可能是我要找的吗?如果是的话,实施情况如何
关于您可以将它们添加到您提到的
哈希集中,而不是首先将它们添加到列表中。重写Equals
和GetHashCode
方法。例如,您可以这样做
public class Person
{
public string Prename;
public string Lastname;
public Person(string pre, string last)
{
Prename = pre; Lastname = last;
}
public override bool Equals(object obj)
{
Person p = obj as Person;
//can make this check case insensitive using the overload
return (Prename + Lastname).Equals(p.Prename + p.Lastname);
}
public override int GetHashCode()
{
return (Prename + Lastname).GetHashCode();
}
}
这样,当您将它们添加到哈希集中时,将不会添加重复项。如果您已经有了一个列表,那么可以像下面这样使用HashSet的
构造函数重载:
class Person
{
public string Prename;
public string Lastname;
public CustomObj(string pre, string last)
{
Prename = pre;
Lastname = last;
}
}
HashSet<Person> hsPerson = new HashSet<Person>(myExistingList);
public void Add(Person person)
{
if (!_list.Any(p => p.Prename == person.PreName && p.Lastname == person.Lastname))
{
_list.Add(person);
}
}
HashSet hsPerson=newhashset(myExistingList);
您将得到一个Person
对象的HashSet
,该对象不会有重复项
我上面的实现假设一个重复的人在连接后具有相同的prename
和lastname
,但是您可以将其更改为您喜欢的内容。如果您不关心集合中元素的顺序,那么这就是方法
它的方法几乎与List
的方法相同,因为它们实现了诸如ICollection
和IEnumerable
等公共接口。以下是一个示例:
HashSet<Person> people = new HashSet<Person>();
var heko = new Person("heko", "17");
people.Add(heko); // people now contains heko
people.Add(heko); // people still contains only heko since duplicates are not allowed
people.Add(new Person("Nikola", "Dimitroff")); // people contains heko and nikola
HashSet-people=newhashset();
var heko=新人(“heko”,“17”);
人物。添加(heko);//人们现在包含了heko
人物。添加(heko);//因为不允许重复,所以人们仍然只包含heko
人物。添加(新人物(“尼古拉”、“迪米特洛夫”);//人们包括赫科和尼古拉
有几件事需要注意。首先,由于HashSet
没有保持元素的顺序,因此无法通过元素的索引获取元素,即people[0]
是无效的操作。要枚举集合中的人员,请使用foreach
其次,HashSet
在比较项目时使用=
运算符和GetHashCode
方法。如果你认为代码<新的人(“Heo”,17)=新的人(“HEKO”,“17”)< /P> > P > >如果你想用你的自定义对象使用<代码> HasStuts< /C>或任何<代码>不同的< /代码>操作,你可以让你的自定义对象实现接口。(遵循该页面上的所有指导,包括覆盖GetHashCode
)。完成后,BCL集合和LINQ操作将按照您希望的方式运行
您应该知道,使GetHashCode
使用可以更改的类的属性可能会导致非常糟糕的事情发生(例如,字典或集合中的项目可能会“丢失”)。如果无法使重要属性保持不变,则可以通过创建一个自定义的IList
实现来满足您的要求,该实现封装了一个标准的列表
,并实现集合类型的Add
方法,如下所示:
class Person
{
public string Prename;
public string Lastname;
public CustomObj(string pre, string last)
{
Prename = pre;
Lastname = last;
}
}
HashSet<Person> hsPerson = new HashSet<Person>(myExistingList);
public void Add(Person person)
{
if (!_list.Any(p => p.Prename == person.PreName && p.Lastname == person.Lastname))
{
_list.Add(person);
}
}
此解决方案的效率会低很多,但可能会为您节省一些令人费解的bug。如果Prename
或Lastname
在仍处于HashSet
中时发生更改,会发生什么情况?根据您的GetHashCode
方法,它们不会被找到。我假设OP只是关心添加或过滤列表。如果更新whilst在一个集合中,用一种自定义的方法来检查重复,实现IEqualityComparer
接口可能是有意义的。