una - eliminar valores repetidos en un array c#
Eliminar duplicados de una lista<T> en C# (23)
¿Alguien tiene un método rápido para desduplicar una lista genérica en C #?
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
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.
La
ToList()
devuelve una nueva lista. Esto es necesario, porque los comandos de Linq comoUnion
devuelven el resultado como un resultado de IEnumerable en lugar de modificar la Lista original o devolver una Nueva Lista.
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 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);
}
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
}
}
}
}
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++;
}
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.
Como método auxiliar (sin Linq):
public static List<T> Distinct<T>(this List<T> list)
{
return (new HashSet<T>(list)).ToList();
}
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.
Funcionó para mí. simplemente use
List<Type> liIDs = liIDs.Distinct().ToList<Type>();
Reemplace "Tipo" con su tipo deseado, por ejemplo, int.
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.
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 :)
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();
}
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)
Puedes usar union
obj2 = obj1.Union(obj1).ToList();
Qué tal si:-
var noDupes = list.Distinct().ToList();
¿En .net 3.5?
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 }
*/
Si está utilizando .Net 3+, puede usar Linq.
List<T> withDupes = LoadSomeData();
List<T> noDupes = withDupes.Distinct().ToList();
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 ...)
Un método de extensión podría ser una manera decente de ir ... algo como esto:
public static List<T> Deduplicate<T>(this List<T> listToDeduplicate)
{
return listToDeduplicate.Distinct().ToList();
}
Y luego llamar así, por ejemplo:
List<int> myFilteredList = unfilteredList.Deduplicate();
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;
}
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();
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++;
}
}
}