我有一个清单:
var list = new List<List<int>>();
Run Code Online (Sandbox Code Playgroud)
哪个可以包含
list[0] = {1, 2, 3, 4}
list[1] = {3, 1, 2, 4}
list[2] = {2, 1, 7, 3}
Run Code Online (Sandbox Code Playgroud)
如何检测[0]和[1]之间的重复并删除其中一个?代码是c-sharp.
实际上它不是一个int,但这不应该改变问题.
Jon*_*eet 11
你可以编写自己的实现IEqualityComparer<List<int>>.因为GetHashCode()它只返回列表中元素的所有哈希码的XOR.因为Equals()它会HashSet<int>从第一个列表创建一个新的,并调用HashSet<T>.SetEquals它,传入第二个列表.假设您没有重复的元素.(否则{1,1,2}将等于{1,2,2}但具有不同的哈希码.)
一旦你到目前为止,你可以使用Distinct:
var distinct = list.Distinct(new CustomEqualityComparer());
Run Code Online (Sandbox Code Playgroud)
作为替代方法,您可以使用HashSet<T>作为您的集合类型开始吗?那真的很容易:
var distinct = sets.Distinct(HashSet<int>.CreateSetComparer());
Run Code Online (Sandbox Code Playgroud)
如果您需要列表作为输入,但可以处理集合作为输出:
var distinct = list.Select(x => new HashSet<int>(x))
.Distinct(HashSet<int>.CreateSetComparer());
Run Code Online (Sandbox Code Playgroud)
这里是Jon Skeet所谈论的euqality比较器(当然,他关于使用HashSets的建议也是当然的):
public class EnumerableComparer<T> : IEqualityComparer<IEnumerable<T>>
where T : IComparable<T>
{
public bool Equals(IEnumerable<T> first, IEnumerable<T> second)
{
if (first == second)
return true;
if ((first == null) || (second == null))
return false;
return new HashSet<T>(first).SetEquals(second);
}
public int GetHashCode(IEnumerable<T> enumerable)
{
return enumerable.OrderBy(x => x)
.Aggregate(17, (current, val) => current*23 + val.GetHashCode());
}
}
Run Code Online (Sandbox Code Playgroud)
所以你要做的事情如下:
list.Distinct(new EnumerableComparer());
Run Code Online (Sandbox Code Playgroud)
如果不保证元素是唯一的 - 使用IEqualityComparer我在此处发布的内容:
比较两个集合的相等性,而不管它们中的项目顺序如何
(在之前的编辑中,我错误地发布了一个IEqulityComparer,它在两个列表列表之间进行比较- 在处理分区时可能非常有用,但这是一个不同的主题)