Obteniendo la “diferencia” entre dos matrices en C #?

Digamos que tengo estas dos matrices:

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

Me gustaría obtener las diferencias entre los dos. Sé que podría escribir esto en unas pocas líneas de código, pero quiero asegurarme de que no me falta una función de lenguaje integrado o un método de extensión LINQ.

Idealmente, terminaría con los siguientes tres resultados:

  • Elementos que no están en array1, pero están en array2 (“D”)
  • Elementos que no están en array2, pero están en array1 (“B”)
  • Artículos que están en ambos

¡Gracias por adelantado!

Si tienes LINQ disponible para ti, puedes usar Except y Distinct . Los conjuntos que solicitó en la pregunta son, respectivamente:

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

de las muestras de MSDN 101 LINQ …

 public void Linq52() { int[] numbersA = { 0, 2, 4, 5, 6, 8, 9 }; int[] numbersB = { 1, 3, 5, 7, 8 }; IEnumerable aOnlyNumbers = numbersA.Except(numbersB); Console.WriteLine("Numbers in first array but not second array:"); foreach (var n in aOnlyNumbers) { Console.WriteLine(n); } } 

Estos son los puntos de referencia de los métodos de extensión LINQ. Los resultados se obtuvieron durante el desarrollo de un progtwig real.

Las pruebas: 2 listas (lst1 y lst2) cada aproximadamente 250000 objetos. Cada objeto (clave de clase) contiene una cadena y un número entero. La segunda lista contiene principalmente las mismas entradas que la primera, pero se agregan algunas entradas nuevas y algunas se eliminan.

Probé el método de extensión Except.

var except = lst2.Except (lst1);

Lista lst = except.ToList ();

Estas 2 líneas produjeron 600 elementos de lista de “nuevas adiciones”. Lo sincronicé usando el objeto StopWatch. La velocidad es sorprendente: 220 ms . La computadora que utilicé no es de ninguna manera un “Gonzales rápido”. Core 2 Duo T7700 – 2.4GHz.

Nota:

Aquí está la clase Key, que implementa IEquatable i-face.

 public class Key : IEquatable { 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; } } 

He tenido que hacer cosas similares a esto con grandes conjuntos de datos. Si está lidiando con algunos miles más o menos, use las cosas de Linq, ya que es mucho más claro. Pero si sabe que sus matrices están previamente ordenadas, ejecutar una fusión como esta puede hacerlo significativamente más rápido, ya que solo hace que una pase a través de los datos y no necesita asignar tanta memoria como la versión de Linq.

 int iA = 0; int iB = 0; List inA = new List(); List inB = new List(); List inBoth = new List(); 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++]); } 

Nuevamente, esto solo es realmente necesario si se trata de cientos de miles de valores.

Otra solución sería como a continuación también

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