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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/683310/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 13:18:23  来源:igfitidea点击:

Getting the "diff" between two arrays in C#?

c#arrays

提问by Michael

Let's say I have these two arrays:

假设我有这两个数组:

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

I would like to get the differences between the two. I know I could write this in just a few lines of code, but I want to make sure I'm not missing a built in language feature or a LINQ extension method.

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

Ideally, I would end up with the following three results:

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

  • Items not in array1, but are in array2 ("D")
  • Items not in array2, but are in array1 ("B")
  • Items that are in both
  • 项目不在数组 1 中,但在数组 2 中(“D”)
  • 项目不在 array2 中,但在 array1 中(“B”)
  • 两者中的项目

Thanks in advance!

提前致谢!

采纳答案by Jon Skeet

If you've got LINQ available to you, you can use Exceptand Distinct. The sets you asked for in the question are respectively:

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

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

回答by Muad'Dib

from the MSDN 101 LINQ samples....

来自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);
    }
}

回答by Eclipse

I've had to do things similar to this with very large sets of data. If you're dealing with a few thousand or so, use the Linq stuff since it's much clearer. But if you know that your arrays are pre-sorted, running a merge like this can do it significantly faster, since it only makes one pass through the data and doesn't need to allocate as much memory as the Linq version.

我不得不用非常大的数据集做类似的事情。如果您要处理几千个左右,请使用 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++]);
}

Again, this is really only needed if you are dealing with hundreds of thousands of values.

同样,只有在处理数十万个值时才需要这样做。

回答by Lev Elbert

Here are the benchmarks of LINQ extension methods. The results were obtained during the development of a real program.

以下是 LINQ 扩展方法的基准测试。结果是在开发实际程序期间获得的。

The tests: 2 lists (lst1 and lst2) each approximately 250000 objects. Each object (class Key) contains a string and an integer. The second list mostly contains the same entries as the first one, but some new entries are added and some are removed.

测试:2 个列表(lst1 和 lst2),每个列表大约 250000 个对象。每个对象(Key 类)包含一个字符串和一个整数。第二个列表大部分包含与第一个列表相同的条目,但添加了一些新条目,删除了一些条目。

I tested the Except extension method.

我测试了Except 扩展方法。

var except = lst2.Except(lst1);

var except = lst2.Except(lst1);

List lst = except.ToList();

List lst = except.ToList();

These 2 lines produced 600 items list of “new additions”. I timed it using the StopWatch object. The speed is astonishing:220 ms. The computer I used is by no means a “speedy Gonzales”. Core 2 Duo T7700 – 2.4GHz.

这 2 行产生了 600 项“新增项”列表。我使用 StopWatch 对象对其计时。速度惊人:220 毫秒。我使用的计算机绝不是“快速冈萨雷斯”。酷睿 2 双核 T7700 – 2.4GHz。

Note:

笔记:

Here is the class Key, which implements IEquatable i-face.

这是 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;
    }
}

回答by Maddy

Another solution would be like below as well

另一种解决方案也如下所示

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