我们说我有一个1到10.000.000个项目的列表。类型是List。 CustomObj看起来像这样:
class Person
{
public string Prename;
public string Lastname;
public CustomObj(string pre, string last)
{
Prename = pre;
Lastname = last;
}
}
我想确保此列表中的每个人都是独一无二的。因此,如果我尝试添加一个" Tim Stone"并且已经有一个" Tim Stone"在列表中,新的不会被添加或过滤掉。
我尝试使用List.Distinct()函数删除重复项。可悲的是,它对自定义对象的效果并不好,我最终得到了重复项。
HashSet可以,我在寻找什么?如果是这样,实现将如何?
此致
答案 0 :(得分:1)
如您所述,您可以将它们添加到HashSet
,而不是先将它们添加到列表中。覆盖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
时,不会添加重复项。如果您已有列表,则可以使用HashSet's
构造函数重载,如下所示:
HashSet<Person> hsPerson = new HashSet<Person>(myExistingList);
您最终会得到HashSet
个Person
个不会重复的对象。
我上面的实现假设重复是指一旦他们重新连接就具有相同prename
和lastname
的人,但您可以将其更改为您喜欢的内容。
答案 1 :(得分:1)
如果您不关心收藏中元素的订单,那么HashSet
就可以了。
它的方法几乎与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[0]
是无效操作。要枚举集合中的人使用foreach
。
其次,HashSet
在比较项目时使用==
运算符和GetHashCode
方法。如果您考虑new Person("heko", 17") == new Person("heko", "17")
。
答案 2 :(得分:0)
如果要对自定义对象使用HashSet<T>
或任何Distinct
操作,可以使自定义对象实现IEquatable界面(遵循该页面上的所有指导,包括覆盖GetHashCode
)。完成后,BCL集合和LINQ操作将按照您希望的方式运行。
您应该知道,使GetHashCode
使用可以更改的类的属性可能会导致非常糟糕的事情发生(例如,字典或集合中的项可能会“丢失”)。如果您无法使重要属性不可变,则可以通过创建IList<T>
的自定义实现来满足您的要求,该实现包装标准List<T>
并实现集合类型的Add
方法,如这样:
public void Add(Person person)
{
if (!_list.Any(p => p.Prename == person.PreName && p.Lastname == person.Lastname))
{
_list.Add(person);
}
}
此解决方案的效率会低得多,但可能会为您节省一些令人费解的错误。