c# - Eliminar duplicados de una lista <T> en C #


11 Answers

Si está utilizando .Net 3+, puede usar Linq.

List<T> withDupes = LoadSomeData();
List<T> noDupes = withDupes.Distinct().ToList();
Question

¿Alguien tiene un método rápido para desduplicar una lista genérica en C #?




Simplemente inicialice un HashSet con una lista del mismo tipo:

var noDupes = new HashSet<T>(withDupes);

O, si quieres una lista devuelta:

var noDupsList = new HashSet<T>(withDupes).ToList();



Funcionó para mí. simplemente use

List<Type> liIDs = liIDs.Distinct().ToList<Type>();

Reemplace "Tipo" con su tipo deseado, por ejemplo, int.




Como kronoz dijo en .Net 3.5, puedes usar Distinct() .

En .Net 2 puedes imitarlo:

public IEnumerable<T> DedupCollection<T> (IEnumerable<T> input) 
{
    var passedValues = new HashSet<T>();

    // Relatively simple dupe check alg used as example
    foreach(T item in input)
        if(passedValues.Add(item)) // True if item is new
            yield return item;
}

Esto podría usarse para deduplicar cualquier colección y devolverá los valores en el orden original.

Normalmente, es mucho más rápido filtrar una colección (como lo hacen Distinct() y esta muestra) que eliminar elementos de ella.




En Java (supongo que C # es más o menos idéntico):

list = new ArrayList<T>(new HashSet<T>(list))

Si realmente querías mutar la lista original:

List<T> noDupes = new ArrayList<T>(new HashSet<T>(list));
list.clear();
list.addAll(noDupes);

Para conservar el orden, simplemente reemplace HashSet con LinkedHashSet.




Aquí hay un método de extensión para eliminar los duplicados adyacentes in-situ. Llame a Sort () primero y pase el mismo IComparer. Esto debería ser más eficiente que la versión de Lasse V. Karlsen que llama a RemoveAt repetidamente (lo que resulta en múltiples movimientos de memoria de bloque).

public static void RemoveAdjacentDuplicates<T>(this List<T> List, IComparer<T> Comparer)
{
    int NumUnique = 0;
    for (int i = 0; i < List.Count; i++)
        if ((i == 0) || (Comparer.Compare(List[NumUnique - 1], List[i]) != 0))
            List[NumUnique++] = List[i];
    List.RemoveRange(NumUnique, List.Count - NumUnique);
}



Usa el método de unión de Linq.

Nota: esta solución no requiere conocimiento de Linq, aparte de que existe.

Código

Comience agregando lo siguiente a la parte superior de su archivo de clase:

using System.Linq;

Ahora, puede usar lo siguiente para eliminar duplicados de un objeto llamado, obj1 :

obj1 = obj1.Union(obj1).ToList();

Nota: Renombra obj1 al nombre de tu objeto.

Cómo funciona

  1. El comando Unión enumera una de cada entrada de dos objetos de origen. Como obj1 es ambos objetos de origen, esto reduce obj1 a una de cada entrada.

  2. La ToList() devuelve una nueva lista. Esto es necesario, porque los comandos de Linq como Union devuelven el resultado como un resultado de IEnumerable en lugar de modificar la Lista original o devolver una Nueva Lista.




Puedes usar union

obj2 = obj1.Union(obj1).ToList();



Hay muchas formas de resolverlo: el problema de los duplicados en la Lista, a continuación, es uno de ellos:

List<Container> containerList = LoadContainer();//Assume it has duplicates
List<Container> filteredList = new  List<Container>();
foreach (var container in containerList)
{ 
  Container duplicateContainer = containerList.Find(delegate(Container checkContainer)
  { return (checkContainer.UniqueId == container.UniqueId); });
   //Assume 'UniqueId' is the property of the Container class on which u r making a search

    if(!containerList.Contains(duplicateContainer) //Add object when not found in the new class object
      {
        filteredList.Add(container);
       }
  }

Saludos Ravi Ganesan




La respuesta de David J. es un buen método, sin necesidad de objetos adicionales, clasificación, etc. Sin embargo, se puede mejorar:

for (int innerIndex = items.Count - 1; innerIndex > outerIndex ; innerIndex--)

Por lo tanto, el bucle externo va desde arriba hacia abajo para toda la lista, pero el bucle interno va hacia abajo "hasta que se alcanza la posición del bucle exterior".

El bucle externo se asegura de que se procese la lista completa, el bucle interno encuentra los duplicados reales, solo pueden suceder en la parte que el bucle externo aún no ha procesado.

O si no quiere hacer un movimiento ascendente para el bucle interno, puede hacer que el bucle interno comience en outerIndex + 1.




Al instalar el paquete MoreLINQ través de Nuget, puede distinguir fácilmente la lista de objetos por una propiedad

IEnumerable<Catalogue> distinctCatalogues = catalogues.DistinctBy(c => c.CatalogueCode); 



Related


Tags

c#   generics