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

Viewed 61539

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.

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

Thanks in advance!

5 Answers

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

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

from the 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);
    }
}

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.

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.

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