比较两个庞大(>50.000项)的最快(和最少资源密集型)的方法是什么,从而得到如下所示的两个列表:
在第一个列表中出现但在第二个列表中没有出现的项目
出现在第二个列表中但不在第一个列表中的项目
目前,我正在使用列表或IReadOnlyCollection,并在linq查询中解决这个问题:
var list1 = list.Where(i => !list2.Contains(i)).ToList();
var list2 = list2.Where(i => !list.Contains(i)).ToList();
但这并不像我想的那样好。
有什么想法使这更快和更少的资源密集,因为我需要处理很多列表?
不是针对这个问题,但是这里有一些代码来比较相等和不相等的列表!相同的对象:
public class EquatableList<T> : List<T>, IEquatable<EquatableList<T>> where T : IEquatable<T>
/// <summary>
/// True, if this contains element with equal property-values
/// </summary>
/// <param name="element">element of Type T</param>
/// <returns>True, if this contains element</returns>
public new Boolean Contains(T element)
{
return this.Any(t => t.Equals(element));
}
/// <summary>
/// True, if list is equal to this
/// </summary>
/// <param name="list">list</param>
/// <returns>True, if instance equals list</returns>
public Boolean Equals(EquatableList<T> list)
{
if (list == null) return false;
return this.All(list.Contains) && list.All(this.Contains);
}
using System.Collections.Generic;
using System.Linq;
namespace YourProject.Extensions
{
public static class ListExtensions
{
public static bool SetwiseEquivalentTo<T>(this List<T> list, List<T> other)
where T: IEquatable<T>
{
if (list.Except(other).Any())
return false;
if (other.Except(list).Any())
return false;
return true;
}
}
}
有时,您只需要知道两个列表是否不同,而不需要知道这些差异是什么。在这种情况下,考虑将此扩展方法添加到项目中。注意,你列出的对象应该实现IEquatable!
用法:
public sealed class Car : IEquatable<Car>
{
public Price Price { get; }
public List<Component> Components { get; }
...
public override bool Equals(object obj)
=> obj is Car other && Equals(other);
public bool Equals(Car other)
=> Price == other.Price
&& Components.SetwiseEquivalentTo(other.Components);
public override int GetHashCode()
=> Components.Aggregate(
Price.GetHashCode(),
(code, next) => code ^ next.GetHashCode()); // Bitwise XOR
}
无论Component类是什么,这里为Car显示的方法应该几乎相同地实现。
注意我们如何编写GetHashCode是非常重要的。为了正确地实现IEquatable, Equals和GetHashCode必须以逻辑兼容的方式操作实例的属性。
Two lists with the same contents are still different objects, and will produce different hash codes. Since we want these two lists to be treated as equal, we must let GetHashCode produce the same value for each of them. We can accomplish this by delegating the hashcode to every element in the list, and using the standard bitwise XOR to combine them all. XOR is order-agnostic, so it doesn't matter if the lists are sorted differently. It only matters that they contain nothing but equivalent members.
注意:这个奇怪的名字是为了暗示这个方法不考虑列表中元素的顺序。如果您确实关心列表中元素的顺序,则此方法不适合您!