假设我有这两个数组:
var array1 = new[] {"A", "B", "C"};
var array2 = new[] {"A", "C", "D"};
我想了解两者之间的差异。我知道我可以用几行代码编写它,但我想确保我没有错过内置语言功能或LINQ扩展方法。
理想情况下,我最终会得到以下三个结果:
提前致谢!
答案 0 :(得分:103)
如果您可以使用LINQ,则可以使用Except
和Distinct
。您在问题中要求的集合分别为:
- array2.Except(array1)
- array1.Except(array2)
- array1.Intersect(array2)
答案 1 :(得分:11)
public void Linq52() {
int[] numbersA = { 0, 2, 4, 5, 6, 8, 9 };
int[] numbersB = { 1, 3, 5, 7, 8 };
IEnumerable<int> aOnlyNumbers = numbersA.Except(numbersB);
Console.WriteLine("Numbers in first array but not second array:");
foreach (var n in aOnlyNumbers) {
Console.WriteLine(n);
}
}
答案 2 :(得分:4)
这是LINQ扩展方法的基准。结果是在制定真实计划期间获得的。
测试: 2列出(lst1和lst2)每个约250000个对象。每个对象(类Key)包含一个字符串和一个整数。第二个列表主要包含与第一个列表相同的条目,但是添加了一些新条目,并删除了一些条目。
我测试了Except扩展方法。
var except = lst2.Except(lst1);
列出lst = except.ToList();
这两行产生了600项“新增”项目清单。我使用StopWatch对象计时。速度惊人: 220 ms 。我使用的计算机绝不是“快速的冈萨雷斯”。 Core 2 Duo T7700 - 2.4GHz。
注意:
这是类Key,它实现了IEquatable i-face。
public class Key : IEquatable<Key>
{
public int Index { get; private set; }
public string Name { get; private set; }
public Key(string keyName, int sdIndex)
{
this.Name = keyName;
this.Index = sdIndex;
}
// IEquatable implementation
public bool Equals(Key other)
{
//Check whether the compared object is null.
if (Object.ReferenceEquals(other, null)) return false;
//Check whether the compared object references the same data.
if (Object.ReferenceEquals(this, other)) return true;
//Check whether the products' properties are equal.
return Index.Equals(other.Index) && Name.Equals(other.Name);
}
// If Equals() returns true for a pair of objects
// then GetHashCode() must return the same value for these objects.
public override int GetHashCode()
{
//Get hash code for the name field if it is not null.
int hashKeyName = Name == null ? 0 : Name.GetHashCode();
//Get hash code for the index field.
int hashKeyIndex = Index.GetHashCode();
//Calculate the hash code for the Key.
return hashKeyName ^ hashKeyIndex;
}
}
答案 3 :(得分:2)
我必须使用非常大的数据集来做类似的事情。如果你要处理几千左右,请使用Linq的东西,因为它更清晰。但是如果你知道你的数组是预先排序的,那么运行这样的合并可以显着加快它的速度,因为它只需要一次通过数据,而不需要分配与Linq版本一样多的内存。
int iA = 0;
int iB = 0;
List<int> inA = new List<int>();
List<int> inB = new List<int>();
List<int> inBoth = new List<int>();
while (iA < numbersA.Length && iB < numbersB.Length)
{
if (numbersA[iA] < numbersB[iB])
{
inA.Add(numbersA[iA++]);
}
else if (numbersA[iA] == numbersB[iB])
{
inBoth.Add(numbersA[iA++]);
++iB;
}
else
{
inB.Add(numbersB[iB++]);
}
}
while (iA < numbersA.Length)
{
inA.Add(numbersA[iA++]);
}
while (iB < numbersB.Length)
{
inB.Add(numbersB[iB++]);
}
同样,只有在处理数十万个值时才需要这样做。
答案 4 :(得分:1)
另一个解决方案也将如下所示
int[] arr1 = new int[] { 45, 26, 99, 55, 36 };
int[] arr2 = new int[] { 45, 26, 99, 20, 36 };
var res = arr1.Union(arr2).Except(arr1.Intersect(arr2));