Tengo una pequeña lista de bytes y quiero probar que todos son valores diferentes. Por ejemplo, tengo esto:
List<byte> theList = new List<byte> { 1,4,3,6,1 };
¿Cuál es la mejor forma de comprobar si todos los valores son distintos o no?
Tengo una pequeña lista de bytes y quiero probar que todos son valores diferentes. Por ejemplo, tengo esto:
List<byte> theList = new List<byte> { 1,4,3,6,1 };
¿Cuál es la mejor forma de comprobar si todos los valores son distintos o no?
Respuestas:
bool isUnique = theList.Distinct().Count() == theList.Count();
Aquí hay otro enfoque que es más eficiente que Enumerable.Distinct+ Enumerable.Count(más si la secuencia no es un tipo de colección). Utiliza un HashSet<T>que elimina los duplicados, es muy eficiente en las búsquedas y tiene una propiedad de recuento:
var distinctBytes = new HashSet<byte>(theList);
bool allDifferent = distinctBytes.Count == theList.Count;
u otro enfoque, más sutil y eficiente:
var diffChecker = new HashSet<byte>();
bool allDifferent = theList.All(diffChecker.Add);
HashSet<T>.Adddevuelve falsesi el elemento no se pudo agregar porque ya estaba en el HashSet. Enumerable.Allse detiene en el primer "falso".
Assert.IsTrue(samples.Add(AwesomeClass.GetUnique()));. Fueron y son :) +1 para ti Tim :)
bool allDifferent = theList.All(s => diffChecker.Add(s))
List.All(HashSet.Add)) parece ser mucho más rápido que los otros dos en casi todos los casos
Bien, aquí está el método más eficiente que se me ocurre usando .Net estándar
using System;
using System.Collections.Generic;
public static class Extension
{
public static bool HasDuplicate<T>(
this IEnumerable<T> source,
out T firstDuplicate)
{
if (source == null)
{
throw new ArgumentNullException(nameof(source));
}
var checkBuffer = new HashSet<T>();
foreach (var t in source)
{
if (checkBuffer.Add(t))
{
continue;
}
firstDuplicate = t;
return true;
}
firstDuplicate = default(T);
return false;
}
}
Básicamente, ¿cuál es el punto de enumerar la secuencia completa dos veces si todo lo que quieres hacer es encontrar el primer duplicado?
Podría optimizar esto más colocando una carcasa especial en secuencias vacías y de un solo elemento, pero eso se depreciaría de la legibilidad / mantenibilidad con una ganancia mínima.
sequencedebería ser source). Pero funciona muy bien una vez que se arreglan
if (!checkBuffer.Add(t)) { firstDuplicate = t; return true }al día.
La lógica similar a Distinctusar GroupBy:
var isUnique = theList.GroupBy(i => i).Count() == theList.Count;
theList.GroupBy(o => o.SomeProperty).Count() == theList.Count;mientras Distinct () no lo permite.
Hay muchas soluciones.
Y sin duda más bellas con el uso de LINQ como "juergen d" y "Tim Schmelter" mencionado.
Pero, si descubres "Complejidad" y velocidad, la mejor solución será implementarla tú mismo. Una de las soluciones será crear una matriz de tamaño N (para el byte es 256). Y repita la matriz, y en cada iteración probará el índice del número coincidente si el valor es 1 si lo hace, eso significa que ya incrementé el índice de la matriz y, por lo tanto, la matriz no es distinta, de lo contrario, incrementaré la celda de la matriz y continuaré verificando .
Y otra solución, si desea encontrar valores duplicados.
var values = new [] { 9, 7, 2, 6, 7, 3, 8, 2 };
var sorted = values.ToList();
sorted.Sort();
for (var index = 1; index < sorted.Count; index++)
{
var previous = sorted[index - 1];
var current = sorted[index];
if (current == previous)
Console.WriteLine(string.Format("duplicated value: {0}", current));
}
Salida:
duplicated value: 2
duplicated value: 7
Verifico si un IEnumerable (aray, lista, etc.) es único como este:
var isUnique = someObjectsEnum.GroupBy(o => o.SomeProperty).Max(g => g.Count()) == 1;