c# - tiene - cómo verificar si el objeto ya existe en una lista
saber si existe una columna en datagridview c# (8)
Tengo una lista
List<MyObject> myList
y estoy agregando elementos a una lista y quiero verificar si ese objeto ya está en la lista.
entonces antes de hacer esto:
myList.Add(nextObject);
Quiero ver si nextObject ya está en la lista.
el objeto "MyObject" tiene varias propiedades, pero la comparación se basa en la coincidencia en dos propiedades.
¿Cuál es la mejor manera de hacer una verificación antes de agregar un nuevo "MyObject" a esta lista de "MyObject" s
la única solución que pensé fue cambiar de una lista a un diccionario y convertirla en una cadena concatenada de las propiedades (esto parece un poco poco elegante)
cualquier otra solución de limpieza usando list o LINQ u otra cosa?
¿Estás seguro de que necesitas una lista en este caso? Si está completando la lista con muchos elementos, el rendimiento se verá myList.Contains
con myList.Contains
o myList.Any
; el tiempo de ejecución será cuadrático. Es posible que desee considerar el uso de una mejor estructura de datos. Por ejemplo,
public class MyClass
{
public string Property1 { get; set; }
public string Property2 { get; set; }
}
public class MyClassComparer : EqualityComparer<MyClass>
{
public override bool Equals(MyClass x, MyClass y)
{
if(x == null || y == null)
return x == y;
return x.Property1 == y.Property1 && x.Property2 == y.Property2;
}
public override int GetHashCode(MyClass obj)
{
return obj == null ? 0 : (obj.Property1.GetHashCode() ^ obj.Property2.GetHashCode());
}
}
Puede usar un HashSet de la siguiente manera:
var set = new HashSet<MyClass>(new MyClassComparer());
foreach(var myClass in ...)
set.Add(myClass);
Por supuesto, si esta definición de igualdad para MyClass
es ''universal'', no necesita escribir una implementación de IEqualityComparer
; podría simplemente anular GetHashCode
e Equals
en la clase misma.
Aquí hay una aplicación de consola rápida para describir el concepto de cómo resolver su problema.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication3
{
public class myobj
{
private string a = string.Empty;
private string b = string.Empty;
public myobj(string a, string b)
{
this.a = a;
this.b = b;
}
public string A
{
get
{
return a;
}
}
public string B
{
get
{
return b;
}
}
}
class Program
{
static void Main(string[] args)
{
List<myobj> list = new List<myobj>();
myobj[] objects = { new myobj("a", "b"), new myobj("c", "d"), new myobj("a", "b") };
for (int i = 0; i < objects.Length; i++)
{
if (!list.Exists((delegate(myobj x) { return (string.Equals(x.A, objects[i].A) && string.Equals(x.B, objects[i].B)) ? true : false; })))
{
list.Add(objects[i]);
}
}
}
}
}
¡Disfrutar!
Depende de las necesidades de la situación específica. Por ejemplo, el enfoque del diccionario sería bastante bueno suponiendo:
- La lista es relativamente estable (no muchas inserciones / eliminaciones, para qué diccionarios no están optimizados)
- La lista es bastante grande (de lo contrario, la sobrecarga del diccionario no tiene sentido).
Si lo anterior no es cierto para su situación, solo use Any()
:
Item wonderIfItsPresent = ...
bool containsItem = myList.Any(item => item.UniqueProperty == wonderIfItsPresent.UniqueProperty);''
Esto enumerará a través de la lista hasta que encuentre una coincidencia, o hasta que llegue al final.
Editar: Primero dije:
Lo que no es elegante acerca de la solución del diccionario. Me parece perfectamente elegante, especialmente porque solo necesita establecer el comparador en la creación del diccionario.
Por supuesto, sin embargo, es poco elegante usar algo como clave cuando también es el valor.
Por lo tanto, usaría un HashSet. Si las operaciones posteriores requerían indexación, crearía una lista cuando finalizara la adición; de lo contrario, simplemente use el hashset.
Otro punto para mencionar es que debe asegurarse de que su función de igualdad sea la esperada. Debe anular el método equals para configurar qué propiedades de su objeto deben coincidir para que dos instancias se consideren iguales.
Entonces puedes hacer mylist.contains (item)
Si es sostenible usar esas 2 propiedades, podrías:
bool alreadyExists = myList.Any(x=> x.Foo=="ooo" && x.Bar == "bat");
Simple pero funciona
MyList.Remove(nextObject)
MyList.Add(nextObject)
o
if (!MyList.Contains(nextObject))
MyList.Add(nextObject);
Simplemente use el método Contains . Tenga en cuenta que funciona basado en la función de igualdad Equals
bool alreadyExist = list.Contains(item);