Utilizando LINQ, de un List<int>, ¿cómo puedo recuperar una lista que contiene las entradas repetidas más de una vez y sus valores?

InformationsquelleAutor Mirko Arcese | 2013-08-31

7 Comentarios

  1. 463

    La forma más sencilla de resolver el problema es agrupar los elementos en base a su valor y, a continuación, elija un representante del grupo, si hay más de un elemento en el grupo. En LINQ, esto se traduce en:

    var query = lst.GroupBy(x => x)
                  .Where(g => g.Count() > 1)
                  .Select(y => y.Key)
                  .ToList();

    Si quieres saber cómo muchas veces los elementos se repiten, se puede utilizar:

    var query = lst.GroupBy(x => x)
                  .Where(g => g.Count() > 1)
                  .Select(y => new { Element = y.Key, Counter = y.Count() })
                  .ToList();

    Esto devolverá una List de un tipo anónimo, y cada elemento tendrá las propiedades Element y Counter, para recuperar la información que usted necesita.

    Y por último, si se trata de un diccionario que busca, puede utilizar

    var query = lst.GroupBy(x => x)
                  .Where(g => g.Count() > 1)
                  .ToDictionary(x => x.Key, y => y.Count());

    Esto devolverá un diccionario, con su elemento clave, y el número de veces que se repite un valor.

    • Ahora, simplemente, una maravilla, vamos a decir que duplican int están distribuidos en n las matrices de int, estoy usando el diccionario y bucle for para entender array que contiene un duplicado y eliminar de acuerdo a una lógica de distribución, hay una manera más rápida de linq (preguntando) para obtener ese resultado ? gracias de antemano por su interés.
    • Yo estoy haciendo algo parecido a esto : code for (int i = 0; i < duplicados.Count; i++) { int duplicado = duplicados[i]; duplicatesLocation.Agregar(duplicados, nueva Lista de<int>()); for (int k = 0; k < hitsList.Length; k++) { if (hitsList[k].Contiene(por duplicado)) { duplicatesLocation.ElementAt(i).Valor.Agregar(k); } } // eliminar duplicados de acuerdo a algunas reglas. } code
    • si desea encontrar duplicados en una lista de matrices, dar una mirada a SelectMany
    • Estoy buscando duplicados de un array de listas, pero no entiendo cómo selectmany me puede ayudar a hacerlo
    • Eso es muy bonito, gracias u para la explicación y la enseñanza, así que voy a pasar un array de listas para LINQ, ahora, despues de todo estoy usando encontrar para saber en qué lista se encuentran los duplicados, la obtención de un diccionario, es posible hacerlo dentro de la consulta de LINQ en la manera en que el resultado es la CLAVE duplicados – VALOR de los índices de la lista que contiene duplicados ?
    • hecho hombre 😀 stackoverflow.com/questions/18561472/…
    • He contestado allí.
    • Tengo un error «El nombre de la » g » no existe en el contexto actual» para el segundo bloque de código.
    • He corregido la errata, gracias
    • impresionante explicación y consultas muchas gracias
    • brillante respuesta
    • Esta es una fantástica y útil respuesta. Incluso he podido comprobar duplicados en una lista de cadenas basadas en un menor subcadena de la sección y a devolver la totalidad de las filas involucradas con: GroupBy( línea => línea de.Substring( 2, 9 ) ).Donde( grp => grp.Count() > 1 ).SelectMany( grp => grp )
    • Para comprobar si cualquier colección tiene más de un elemento, si es más eficaz el uso de Saltar(1).Ninguna() en lugar de Count(). Imaginar una colección con 1000 elementos. Skip(1).Ninguna() detecta que hay más de 1 una vez que encuentra el 2º elemento. Mediante Count() requiere para tener acceso a la colección completa.

  2. 106

    Averiguar si un enumerable contiene cualquier duplicado :

    var anyDuplicate = enumerable.GroupBy(x => x.Key).Any(g => g.Count() > 1);

    Averiguar si todos valores en un enumerable son único :

    var allUnique = enumerable.GroupBy(x => x.Key).All(g => g.Count() == 1);
    • Hay alguna posibilidad de que estas no siempre son booleano opuestos? anyDuplicate == !allUnique en todos los casos.
    • Ellos siempre están booleano opuestos
  3. 19

    Otra forma es utilizando HashSet:

    var hash = new HashSet<int>();
    var duplicates = list.Where(i => !hash.Add(i));

    Si quieres valores únicos en su duplicados de la lista:

    var myhash = new HashSet<int>();
    var mylist = new List<int>(){1,1,2,2,3,3,3,4,4,4};
    var duplicates = mylist.Where(item => !myhash.Add(item)).ToList().Distinct().ToList();

    Aquí es la misma solución como una extensión genérica del método:

    public static class Extensions
    {
      public static IEnumerable<TSource> GetDuplicates<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> selector, IEqualityComparer<TKey> comparer)
      {
        var hash = new HashSet<TKey>(comparer);
        return source.Where(item => !hash.Add(selector(item))).ToList();
      }
    
      public static IEnumerable<TSource> GetDuplicates<TSource>(this IEnumerable<TSource> source, IEqualityComparer<TSource> comparer)
      {
        return source.GetDuplicates(x => x, comparer);      
      }
    
      public static IEnumerable<TSource> GetDuplicates<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> selector)
      {
        return source.GetDuplicates(selector, null);
      }
    
      public static IEnumerable<TSource> GetDuplicates<TSource>(this IEnumerable<TSource> source)
      {
        return source.GetDuplicates(x => x, null);
      }
    }
    • Esto no funciona como se esperaba. El uso de List<int> { 1, 2, 3, 4, 5, 2 } como la fuente, el resultado es un IEnumerable<int> con un elemento que tiene el valor de 1 (donde la correcta duplicar el valor es 2)
    • ayer, creo que te equivocas. Echa un vistazo a este ejemplo: dotnetfiddle.net/GUnhUl
    • Su violín imprime el resultado correcto. Sin embargo, he añadido la línea Console.WriteLine("Count: {0}", duplicates.Count()); directamente debajo de él y se imprime 6. A menos que me estoy perdiendo algo acerca de los requisitos para esta función, no sólo debe ser de 1 elemento en la colección resultante.
    • ayer, es un bug causado por LINQ ejecución diferida. He añadido ToList con el fin de solucionar el problema, pero esto significa que el método se ejecuta tan pronto como se llama, y no cuando se itera sobre los resultados.
    • var hash = new HashSet<int>(); var duplicates = list.Where(i => !hash.Add(i)); llevará a una lista que incluye todas las apariciones de duplicados. Así que si usted tiene cuatro apariciones de 2 en su lista, entonces su duplicado de la lista contendrá tres apariciones de 2, ya que sólo uno de los 2 puede ser añadido a la HashSet. Si usted quiere que su lista para contener valores únicos para cada duplicado, utilice este código: var duplicates = mylist.Where(item => !myhash.Add(item)).ToList().Distinct().ToList();
  4. 10

    Usted puede hacer esto:

    var list = new[] {1,2,3,1,4,2};
    var duplicateItems = list.Duplicates();

    Con estos métodos de extensión:

    public static class Extensions
    {
        public static IEnumerable<TSource> Duplicates<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> selector)
        {
            var grouped = source.GroupBy(selector);
            var moreThan1 = grouped.Where(i => i.IsMultiple());
            return moreThan1.SelectMany(i => i);
        }
    
        public static IEnumerable<TSource> Duplicates<TSource, TKey>(this IEnumerable<TSource> source)
        {
            return source.Duplicates(i => i);
        }
    
        public static bool IsMultiple<T>(this IEnumerable<T> source)
        {
            var enumerator = source.GetEnumerator();
            return enumerator.MoveNext() && enumerator.MoveNext();
        }
    }

    Utilizando IsMultiple() en el Duplicados método es más rápido que el Count (), ya que esto no recorrer toda la colección.

    • Si usted mira en la fuente de referencia para Agrupar usted puede ver que Count() se pre calculada y su solución es probablemente más lento.
    • Tienes razón, en este caso, es más rápido y la implementatation es probable que nunca cambia… pero depende de un detalle de implementación de la implementación de la clase detrás de IGrouping. Con mi establecimiento, usted sabe que nunca va a recorrer toda la colección.
    • así que contar [Count()] es básicamente diferente de recorrer toda la lista. Count() es pre-calculadas, pero recorrer toda la lista no es.
    • khan: no entiendo la diferencia entre Count() y Count()
    • No debería haber ninguna diferencia que tal vez ¿por qué.
    • IsMultiple NO es hacer un Count(), se detiene Inmediatamente después de 2 elementos. Como Tomar(2).Contar >= 2;

  5. 6

    He creado una extensión de la respuesta a esto podría ser que en tus proyectos, yo creo que este retorno de la mayoría de los casos cuando la búsqueda de duplicados en la Lista o Linq.

    Ejemplo:

    //Dummy class to compare in list
    public class Person
    {
    public int Id { get; set; }
    public string Name { get; set; }
    public string Surname { get; set; }
    public Person(int id, string name, string surname)
    {
    this.Id = id;
    this.Name = name;
    this.Surname = surname;
    }
    }
    //The extention static class
    public static class Extention
    {
    public static IEnumerable<T> getMoreThanOnceRepeated<T>(this IEnumerable<T> extList, Func<T, object> groupProps) where T : class
    { //Return only the second and next reptition
    return extList
    .GroupBy(groupProps)
    .SelectMany(z => z.Skip(1)); //Skip the first occur and return all the others that repeats
    }
    public static IEnumerable<T> getAllRepeated<T>(this IEnumerable<T> extList, Func<T, object> groupProps) where T : class
    {
    //Get All the lines that has repeating
    return extList
    .GroupBy(groupProps)
    .Where(z => z.Count() > 1) //Filter only the distinct one
    .SelectMany(z => z);//All in where has to be retuned
    }
    }
    //how to use it:
    void DuplicateExample()
    {
    //Populate List
    List<Person> PersonsLst = new List<Person>(){
    new Person(1,"Ricardo","Figueiredo"), //fist Duplicate to the example
    new Person(2,"Ana","Figueiredo"),
    new Person(3,"Ricardo","Figueiredo"),//second Duplicate to the example
    new Person(4,"Margarida","Figueiredo"),
    new Person(5,"Ricardo","Figueiredo")//third Duplicate to the example
    };
    Console.WriteLine("All:");
    PersonsLst.ForEach(z => Console.WriteLine("{0} -> {1} {2}", z.Id, z.Name, z.Surname));
    /* OUTPUT:
    All:
    1 -> Ricardo Figueiredo
    2 -> Ana Figueiredo
    3 -> Ricardo Figueiredo
    4 -> Margarida Figueiredo
    5 -> Ricardo Figueiredo
    */
    Console.WriteLine("All lines with repeated data");
    PersonsLst.getAllRepeated(z => new { z.Name, z.Surname })
    .ToList()
    .ForEach(z => Console.WriteLine("{0} -> {1} {2}", z.Id, z.Name, z.Surname));
    /* OUTPUT:
    All lines with repeated data
    1 -> Ricardo Figueiredo
    3 -> Ricardo Figueiredo
    5 -> Ricardo Figueiredo
    */
    Console.WriteLine("Only Repeated more than once");
    PersonsLst.getMoreThanOnceRepeated(z => new { z.Name, z.Surname })
    .ToList()
    .ForEach(z => Console.WriteLine("{0} -> {1} {2}", z.Id, z.Name, z.Surname));
    /* OUTPUT:
    Only Repeated more than once
    3 -> Ricardo Figueiredo
    5 -> Ricardo Figueiredo
    */
    }
    • Considere el uso de Saltar(1).Ninguna() en lugar de Count(). Si usted tiene 1000 duplicados, entonces salta(1).Ninguna() se detendrá después de que se encuentra en el 2do uno. Count() tendrá acceso a todos 1000 elementos.
    • Si se agrega a este método de extensión, considere el uso de HashSet.Agregar en lugar de Agrupar, como suggeted en una de las otras respuestas. Tan pronto como HashSet.Agregar encuentra duplicados se detendrá. Su GroupBy continuará la agrupación de todos los elementos, incluso si en un grupo con más de un elemento se ha encontrado
  6. 3

    Para encontrar los valores duplicados sólo :

    var duplicates = list.GroupBy(x => x.Key).Any(g => g.Count() > 1);

    Por ejemplo.
    var lista = new[] {1,2,3,1,4,2};

    por lo que los grupos por el grupo de los números por sus llaves y va a mantener el recuento(número de veces que se repite) con ella. Después de eso, estamos a sólo la comprobación de los valores que han repetido más de una vez.

    Para encontrar el uniuqe sólo valores :

    var unique = list.GroupBy(x => x.Key).All(g => g.Count() == 1);

    Por ejemplo.
    var lista = new[] {1,2,3,1,4,2};

    por lo que los grupos por el grupo de los números por sus llaves y va a mantener el recuento(número de veces que se repite) con ella. Después de eso, estamos a sólo la comprobación de los valores que han repetido sólo una vez que los medios son únicos.

  7. 1

    Conjunto completo de Linq to SQL extensiones de Duplicados funciones marcada en MS SQL Server. Sin utilizar .ToList() o IEnumerable. Estas consultas en la ejecución de SQL Server en lugar de en la memoria.. Los resultados sólo se devolverá en la memoria.

    public static class Linq2SqlExtensions {
    public class CountOfT<T> {
    public T Key { get; set; }
    public int Count { get; set; }
    }
    public static IQueryable<TKey> Duplicates<TSource, TKey>(this IQueryable<TSource> source, Expression<Func<TSource, TKey>> groupBy)
    => source.GroupBy(groupBy).Where(w => w.Count() > 1).Select(s => s.Key);
    public static IQueryable<TSource> GetDuplicates<TSource, TKey>(this IQueryable<TSource> source, Expression<Func<TSource, TKey>> groupBy)
    => source.GroupBy(groupBy).Where(w => w.Count() > 1).SelectMany(s => s);
    public static IQueryable<CountOfT<TKey>> DuplicatesCounts<TSource, TKey>(this IQueryable<TSource> source, Expression<Func<TSource, TKey>> groupBy)
    => source.GroupBy(groupBy).Where(w => w.Count() > 1).Select(y => new CountOfT<TKey> { Key = y.Key, Count = y.Count() });
    public static IQueryable<Tuple<TKey, int>> DuplicatesCountsAsTuble<TSource, TKey>(this IQueryable<TSource> source, Expression<Func<TSource, TKey>> groupBy)
    => source.GroupBy(groupBy).Where(w => w.Count() > 1).Select(s => Tuple.Create(s.Key, s.Count()));
    }

Dejar respuesta

Please enter your comment!
Please enter your name here