2010-06-29 18 views
5

con los siguientes datosexpresión Lambda para encontrar la diferencia

string[] data = { "a", "a", "b" }; 

me gustaría mucho para encontrar duplicados y obtener este resultado:

a 

probé el siguiente código

var a = data.Distinct().ToList(); 
var b = a.Except(a).ToList(); 

obviamente esto no funcionó, puedo ver lo que está sucediendo arriba, pero no estoy seguro de cómo solucionarlo.

Respuesta

11

Cuando el tiempo de ejecución no es ningún problema, usted podría utilizar

var duplicates = data.Where(s => data.Count(t => t == s) > 1).Distinct().ToList(); 

buen O de edad (n^n) =)

Editar: Ahora, para una mejor solución. =) Si se define un nuevo método de extensión como

static class Extensions 
{   

    public static IEnumerable<T> Duplicates<T>(this IEnumerable<T> input) 
    { 
     HashSet<T> hash = new HashSet<T>(); 
     foreach (T item in input) 
     { 
      if (!hash.Contains(item)) 
      { 
       hash.Add(item); 
      } 
      else 
      { 
       yield return item; 
      } 
     } 
    } 
} 

puede utilizar

var duplicates = data.Duplicates().Distinct().ToArray(); 
+0

Buena solución con el conjunto de hash. Estaba pensando en esa línea, pero claramente todavía no me desperté ... – Noldorin

+0

¡Buena solución con el juego de hash hecho! ¡Sabía que podía hacerlo de esa manera, pero no sabía que era posible extender el lenguaje de esa manera! – user375049

1

Ordene los datos, repítalo y recuerde el último elemento. Cuando el elemento actual es el mismo que el anterior, es un duplicado. Esto se puede implementar fácilmente ya sea iterativamente o usando una expresión lambda en el tiempo O (n * log (n)).

+0

Esto es lo que estoy tratando de hacer, pero aprender a escribir lambdas y no es obvio cómo hacerlo. – user375049

5

utilizar el grupo por la materia, el rendimiento de estos métodos son razonablemente buena. La única preocupación es la gran sobrecarga de memoria si está trabajando con grandes conjuntos de datos.

from g in (from x in data group x by x) 
where g.Count() > 1 
select g.Key; 

-OR si prefieren los métodos de extensión

data.GroupBy(x => x) 
    .Where(x => x.Count() > 1) 
    .Select(x => x.Key) 

Dónde Count() == 1 que es sus artículos distintos y en el Count() > 1 que es uno o más elementos duplicados.

Desde LINQ es una especie de perezoso, si no desea volver a evaluar su cálculo se puede hacer esto:

var g = (from x in data group x by x).ToList(); // grouping result 
// duplicates 
from x in g 
where x.Count() > 1 
select x.Key; 
// distinct 
from x in g 
where x.Count() == 1 
select x.Key; 

Al crear la agrupación de una serie de conjuntos se crearán. Suponiendo que se trata de un conjunto con O(1), la inserción del tiempo de ejecución del grupo por aproximación es O(n). El costo incurrido para cada operación es algo alto, pero debería equivaler a un desempeño casi lineal.

+0

Te votaré pero necesito 15 repeticiones para hacerlo (!) Buen ejemplo :) – user375049

+0

Puedes cambiar tu respuesta preferida si quieres. –

Cuestiones relacionadas