从列表C#删除重复 [英] removing duplicates from a list C#
问题描述
我下面的一个计算器以前的文章了解删除重复在C#中的列表。
I am following a previous post on stackoverflow about removing duplicates from a List in C#.
如果< T>
是一些用户定义的类型,如:
If <T>
is some user defined type like:
class Contact
{
public string firstname;
public string lastname;
public string phonenum;
}
建议的(HashMap的)不删除重复。我想,我必须重新定义一些方法来比较两个对象,是不是?
The suggested (HashMap) doesn't remove duplicate. I think, I have to redefine some method for comparing two objects, isnt it?
推荐答案
A HashSet的< ; T>
的确实的删除重复,因为它是一个集......但只有当你的类型,适当的定义平等
A HashSet<T>
does remove duplicates, because it's a set... but only when your type defines equality appropriately.
我怀疑通过重复你的意思是具有相同的字段值到另一个对象的对象 - 你需要重写等于
/ 的GetHashCode
对于工作,和/或实施 IEquatable<联系与GT;
...或者你可以提供一个的IEqualityComparer<联系与GT;
到的HashSet< T> 。code>构造
I suspect by "duplicate" you mean "an object with equal field values to another object" - you need to override Equals
/GetHashCode
for that to work, and/or implement IEquatable<Contact>
... or you could provide an IEqualityComparer<Contact>
to the HashSet<T>
constructor.
而不是使用 HashSet的<的; T>
你的可以只需调用鲜明
LINQ扩展方法。例如:
Instead of using a HashSet<T>
you could just call the Distinct
LINQ extension method. For example:
list = list.Distinct().ToList();
但同样,你需要提供平等,适当的定义在某种程度上或其他。
But again, you'll need to provide an appropriate definition of equality, somehow or other.
下面是一个示例实现。请注意我是如何使它变的(平等是奇数与可变类型,因为两个对象可以等于一分钟,不等于下一个)和
做
私人领域,具有公共属性。最后,我已经密封类 - 不可变的类型一般应密封,它使平等容易谈论
Here's a sample implementation. Note how I've made it immutable (equality is odd with mutable types, because two objects can be equal one minute and non-equal the next) and made the fields private, with public properties. Finally, I've sealed the class - immutable types should generally be sealed, and it makes equality easier to talk about.
using System;
using System.Collections.Generic;
public sealed class Contact : IEquatable<Contact>
{
private readonly string firstName;
public string FirstName { get { return firstName; } }
private readonly string lastName;
public string LastName { get { return lastName; } }
private readonly string phoneNumber;
public string PhoneNumber { get { return phoneNumber; } }
public Contact(string firstName, string lastName, string phoneNumber)
{
this.firstName = firstName;
this.lastName = lastName;
this.phoneNumber = phoneNumber;
}
public override bool Equals(object other)
{
return Equals(other as Contact);
}
public bool Equals(Contact other)
{
if (object.ReferenceEquals(other, null))
{
return false;
}
if (object.ReferenceEquals(other, this))
{
return true;
}
return FirstName == other.FirstName &&
LastName == other.LastName &&
PhoneNumber == other.PhoneNumber;
}
public override int GetHashCode()
{
// Note: *not* StringComparer; EqualityComparer<T>
// copes with null; StringComparer doesn't.
var comparer = EqualityComparer<string>.Default;
// Unchecked to allow overflow, which is fine
unchecked
{
int hash = 17;
hash = hash * 31 + comparer.GetHashCode(FirstName);
hash = hash * 31 + comparer.GetHashCode(LastName);
hash = hash * 31 + comparer.GetHashCode(PhoneNumber);
return hash;
}
}
}
编辑:好的,响应为的GetHashCode()
执行情况的说明要求:
Okay, in response to requests for an explanation of the GetHashCode()
implementation:
- 我们要结合此对象的属性的哈希码
- 我们正在不检查任何地方无效,所以我们应该假定其中一些人可能为null。
EqualityComparer< T> .DEFAULT
总是处理这一点,这是很好的......所以我用,要得到各个领域的哈希码 - 添加和乘法的方式来几个哈希码组合成一个是标准件由乔希布洛赫建议。还有很多其他的通用散列算法,但是这一个正常工作对于大多数应用程序。
- 我不知道你在默认情况下选中的上下文是否正在编译,所以我'已经把计算在unchecked上下文中。我们的真正的,如果反复乘/加导致溢出不在乎,因为我们不是在寻找一个数量级这样......只是一个数字,我们可以平等反复到达。对象
- We want to combine the hash codes of the properties of this object
- We're not checking for nullity anywhere, so we should assume that some of them may be null.
EqualityComparer<T>.Default
always handles this, which is nice... so I'm using that to get a hash code of each field. - The "add and multiply" approach to combining several hash codes into one is the standard one recommended by Josh Bloch. There are plenty of other general-purpose hashing algorithms, but this one works fine for most applications.
- I don't know whether you're compiling in a checked context by default, so I've put the computation in an unchecked context. We really don't care if the repeated multiply/add leads to an overflow, because we're not looking for a "magnitude" as such... just a number that we can reach repeatedly for equal objects.
处理无效,顺便两种可选的方式:
Two alternative ways of handling nullity, by the way:
public override int GetHashCode()
{
// Unchecked to allow overflow, which is fine
unchecked
{
int hash = 17;
hash = hash * 31 + (FirstName ?? "").GetHashCode();
hash = hash * 31 + (LastName ?? "").GetHashCode();
hash = hash * 31 + (PhoneNumber ?? "").GetHashCode();
return hash;
}
}
或
public override int GetHashCode()
{
// Unchecked to allow overflow, which is fine
unchecked
{
int hash = 17;
hash = hash * 31 + (FirstName == null ? 0 : FirstName.GetHashCode());
hash = hash * 31 + (LastName == null ? 0 : LastName.GetHashCode());
hash = hash * 31 + (PhoneNumber == null ? 0 : PhoneNumber.GetHashCode());
return hash;
}
}
这篇关于从列表C#删除重复的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!