获取C#中两个数组之间的“差异”?
比方说,我有这两个数组:
var array1 = new[] {"A", "B", "C"}; var array2 = new[] {"A", "C", "D"};
我想了解两者之间的差异。 我知道我可以用几行代码写这个,但是我想确保我不缺less内置的语言function或LINQ扩展方法。
理想情况下,我会得到以下三个结果:
- 不在array1中,但在array2(“D”)中的项目
- 不在array2中,但在array1(“B”)中的项目
- 在两个项目
提前致谢!
如果你有LINQ可用,你可以使用Except
和Distinct
。 你在问题中要求的集合分别是:
- array2.Except(array1) - array1.Except(array2) - array1.Intersect(array2)
从MSDN 101 LINQ样本 ….
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); } }
这里是LINQ扩展方法的基准。 结果是在真正的程序开发过程中获得的。
testing:2个列表(lst1和lst2),每个约有250000个对象。 每个对象(类Key)都包含一个string和一个整数。 第二个列表大多包含与第一个列表相同的条目,但是添加了一些新条目,并且删除了一些条目。
我testing了Except扩展方法。
var except = lst2.Except(lst1);
List lst = except.ToList();
这两行产生了600个项目的“新增”列表。 我使用StopWatch对象对其进行了计时。 速度惊人: 220毫秒 。 我用的电脑绝不是“快速的冈萨雷斯”。 酷睿2双核T7700 – 2.4GHz。
注意:
这里是实现IEquatable i-face的类Key。
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; } }
我不得不通过非常大的数据来做类似的事情。 如果你处理几千个左右,使用Linq的东西,因为它更清晰。 但是如果你知道你的数组是预sorting的,那么运行这样的合并可以显着加快数据传输速度,因为它只传递一次数据,而不需要分配与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++]); }
再说一次,如果你正在处理成千上万的值,那么这是唯一需要的。