在C#中获取两个数组之间的“差异”?

时间:2009-03-25 20:28:20

标签: c# arrays

假设我有这两个数组:

var array1 = new[] {"A", "B", "C"};
var array2 = new[] {"A", "C", "D"};

我想了解两者之间的差异。我知道我可以用几行代码编写它,但我想确保我没有错过内置语言功能或LINQ扩展方法。

理想情况下,我最终会得到以下三个结果:

  • 不在array1中但在array2(“D”)
  • 中的项目
  • 不在array2中但在array1(“B”)
  • 中的项目
  • 两者中的项目

提前致谢!

5 个答案:

答案 0 :(得分:103)

如果您可以使用LINQ,则可以使用ExceptDistinct。您在问题中要求的集合分别为:

- array2.Except(array1)
- array1.Except(array2)
- array1.Intersect(array2)

答案 1 :(得分:11)

来自MSDN 101 LINQ samples ....

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));