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





arraylist repetido (20)


Qué tal si:-

var noDupes = list.Distinct().ToList();

¿En .net 3.5?

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




Otra forma en .Net 2.0

    static void Main(string[] args)
    {
        List<string> alpha = new List<string>();

        for(char a = 'a'; a <= 'd'; a++)
        {
            alpha.Add(a.ToString());
            alpha.Add(a.ToString());
        }

        Console.WriteLine("Data :");
        alpha.ForEach(delegate(string t) { Console.WriteLine(t); });

        alpha.ForEach(delegate (string v)
                          {
                              if (alpha.FindAll(delegate(string t) { return t == v; }).Count > 1)
                                  alpha.Remove(v);
                          });

        Console.WriteLine("Unique Result :");
        alpha.ForEach(delegate(string t) { Console.WriteLine(t);});
        Console.ReadKey();
    }



Quizás deberías considerar usar un HashSet .

Desde el enlace de MSDN:

using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        HashSet<int> evenNumbers = new HashSet<int>();
        HashSet<int> oddNumbers = new HashSet<int>();

        for (int i = 0; i < 5; i++)
        {
            // Populate numbers with just even numbers.
            evenNumbers.Add(i * 2);

            // Populate oddNumbers with just odd numbers.
            oddNumbers.Add((i * 2) + 1);
        }

        Console.Write("evenNumbers contains {0} elements: ", evenNumbers.Count);
        DisplaySet(evenNumbers);

        Console.Write("oddNumbers contains {0} elements: ", oddNumbers.Count);
        DisplaySet(oddNumbers);

        // Create a new HashSet populated with even numbers.
        HashSet<int> numbers = new HashSet<int>(evenNumbers);
        Console.WriteLine("numbers UnionWith oddNumbers...");
        numbers.UnionWith(oddNumbers);

        Console.Write("numbers contains {0} elements: ", numbers.Count);
        DisplaySet(numbers);
    }

    private static void DisplaySet(HashSet<int> set)
    {
        Console.Write("{");
        foreach (int i in set)
        {
            Console.Write(" {0}", i);
        }
        Console.WriteLine(" }");
    }
}

/* This example produces output similar to the following:
 * evenNumbers contains 5 elements: { 0 2 4 6 8 }
 * oddNumbers contains 5 elements: { 1 3 5 7 9 }
 * numbers UnionWith oddNumbers...
 * numbers contains 10 elements: { 0 2 4 6 8 1 3 5 7 9 }
 */



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




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



Puedes usar union

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



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



Aquí hay una solución simple que no requiere un LINQ difícil de leer o una clasificación previa de la lista.

   private static void CheckForDuplicateItems(List<string> items)
    {
        if (items == null ||
            items.Count == 0)
            return;

        for (int outerIndex = 0; outerIndex < items.Count; outerIndex++)
        {
            for (int innerIndex = 0; innerIndex < items.Count; innerIndex++)
            {
                if (innerIndex == outerIndex) continue;
                if (items[outerIndex].Equals(items[innerIndex]))
                {
                    // Duplicate Found
                }
            }
        }
    }



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.




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.




Si no te importa el orden, puedes simplemente meter los artículos en un HashSet , si quieres mantener el orden puedes hacer algo como esto:

var unique = new List<T>();
var hs = new HashSet<T>();
foreach (T t in list)
    if (hs.Add(t))
        unique.Add(t);

O la forma Linq:

var hs = new HashSet<T>();
list.All( x =>  hs.Add(x) );

Edición: el método HashSet es el tiempo O(N) espacio O(N) al ordenar y luego hacer único (como lo sugieren @ lassevk y otros) es el tiempo O(N*lgN) y el espacio O(1) , por lo que no es tan Me queda claro (como lo fue a primera vista) que la forma de clasificación es inferior (mis disculpas por el voto negativo temporal ...)




Como método auxiliar (sin Linq):

public static List<T> Distinct<T>(this List<T> list)
{
    return (new HashSet<T>(list)).ToList();
}



Podría ser más fácil simplemente asegurarse de que los duplicados no se agreguen a la lista.

if(items.IndexOf(new_item) < 0) 
    items.add(new_item)



Una implementación intuitiva simple:

public static List<PointF> RemoveDuplicates(List<PointF> listPoints)
{
    List<PointF> result = new List<PointF>();

    for (int i = 0; i < listPoints.Count; i++)
    {
        if (!result.Contains(listPoints[i]))
            result.Add(listPoints[i]);
        }

        return result;
    }



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.




Me gusta usar este comando:

List<Store> myStoreList = Service.GetStoreListbyProvince(provinceId)
                                                 .GroupBy(s => s.City)
                                                 .Select(grp => grp.FirstOrDefault())
                                                 .OrderBy(s => s.City)
                                                 .ToList();

Tengo estos campos en mi lista: Id, Nombre de la tienda, Ciudad, Código postal Quería mostrar la lista de ciudades en un menú desplegable que tiene valores duplicados. solución: agrupar por ciudad y luego elegir el primero para la lista.

Espero que ayude :)




Clasifíquelo, luego marque dos y dos al lado de los otros, ya que los duplicados se agruparán.

Algo como esto:

list.Sort();
Int32 index = 0;
while (index < list.Count - 1)
{
    if (list[index] == list[index + 1])
        list.RemoveAt(index);
    else
        index++;
}



  public static void RemoveDuplicates<T>(IList<T> list )
  {
     if (list == null)
     {
        return;
     }
     int i = 1;
     while(i<list.Count)
     {
        int j = 0;
        bool remove = false;
        while (j < i && !remove)
        {
           if (list[i].Equals(list[j]))
           {
              remove = true;
           }
           j++;
        }
        if (remove)
        {
           list.RemoveAt(i);
        }
        else
        {
           i++;
        }
     }  
  }



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.




Las lambdas y las inferencias tipo están subestimadas. Lambdas puede tener varias declaraciones y se doblan como un objeto delegado compatible automáticamente (solo asegúrese de que la firma coincida) como en:

Console.CancelKeyPress +=
    (sender, e) => {
        Console.WriteLine("CTRL+C detected!\n");
        e.Cancel = true;
    };

Tenga en cuenta que no tengo un new CancellationEventHandler ni tengo que especificar los tipos de sender y e , son inferables del evento. Es por eso que esto es menos engorroso para escribir todo el delegate (blah blah) que también requiere que especifique tipos de parámetros.

Lambdas no necesita devolver nada y la inferencia de tipos es extremadamente poderosa en un contexto como este.

Y, por cierto, siempre puede devolver Lambdas que hacen de Lambdas en el sentido de la programación funcional. Por ejemplo, aquí hay un lambda que hace un lambda que maneja un evento Button.Click:

Func<int, int, EventHandler> makeHandler =
    (dx, dy) => (sender, e) => {
        var btn = (Button) sender;
        btn.Top += dy;
        btn.Left += dx;
    };

btnUp.Click += makeHandler(0, -1);
btnDown.Click += makeHandler(0, 1);
btnLeft.Click += makeHandler(-1, 0);
btnRight.Click += makeHandler(1, 0);

Note el encadenamiento: (dx, dy) => (sender, e) =>

Ahora es por eso que estoy feliz de haber tomado la clase de programación funcional :-)

Aparte de los punteros en C, creo que es otra cosa fundamental que debes aprender :-)







c# generics