我有一份清单:
var list = new List<List<int>>();
可以包含
list[0] = {1, 2, 3, 4}
list[1] = {3, 1, 2, 4}
list[2] = {2, 1, 7, 3}
如何检测[0]和[1]之间的重复并删除其中一个?代码是c-sharp。
实际上它不是一个int,但这不应该改变这个问题。
答案 0 :(得分: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());
作为替代方法,您可以使用HashSet<T>
作为收集类型吗?那么真的很容易:
var distinct = sets.Distinct(HashSet<int>.CreateSetComparer());
如果您需要列表作为输入,但可以处理集合作为输出:
var distinct = list.Select(x => new HashSet<int>(x))
.Distinct(HashSet<int>.CreateSetComparer());
答案 1 :(得分:5)
以下是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());
}
}
所以你会做类似的事情:
list.Distinct(new EnumerableComparer());
如果不保证元素是唯一的 - 请使用我在此处发布的IEqualityComparer
:
Comparing two collections for equality irrespective of the order of items in them
(在以前的编辑中,我错误地发布了一个IEqulityComparer,用于比较两个列表列表 - 在处理分区时可能非常有用,但这是一个不同的主题)
答案 2 :(得分:1)
list[1] = list[1].Except(list[0]).ToList();
这是解决方案,我们需要从数组list[0]
和list[1]
中删除重复的int。其他答案正在处理删除包含相同内容集的数组的情况。
答案 3 :(得分:1)
boolean compareLists(list1, list2) {
// Early rejection
if (list1.size != list2.size) {
return false;
}
// Sort lists and compare each item
sorted1 = sort(list1.clone());
sorted2 = sort(list2.clone());
for (int i=0; i<list1.size; ++i) {
if (sorted1[i]!=sorted2[i]) {
return false;
}
}
return true;
}