2009-03-06 11 views
7

usando C# 3 y .Net Framework 3.5, que tienen un objeto PersonBuscar duplicados de datos de objetos en la lista de objetos

public Person 
{ 
    public int Id { get; set; } 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
    public int SSN { get; set; } 
} 

y tengo una lista de ellos:

List<Person> persons = GetPersons(); 

Cómo ¿Puedo obtener todos los objetos Persona en personas donde el número de Seguro Social no es único en la lista y eliminarlos de la lista de personas e idealmente agregarlos a otra lista llamada "List<Person> dupes"?

La lista original podría ser algo como esto:

persons = new List<Person>(); 
persons.Add(new Person { Id = 1, 
         FirstName = "Chris", 
         LastName="Columbus", 
         SSN=111223333 }); // Is a dupe 
persons.Add(new Person { Id = 1, 
         FirstName = "E.E.", 
         LastName="Cummings", 
         SSN=987654321 }); 
persons.Add(new Person { Id = 1, 
         FirstName = "John", 
         LastName="Steinbeck", 
         SSN=111223333 }); // Is a dupe 
persons.Add(new Person { Id = 1, 
         FirstName = "Yogi", 
         LastName="Berra", 
         SSN=123456789 }); 

Y el resultado final tendría Cummings y Berra en la lista de personas originales y tendría Colón y Steinbeck en una lista llamada incautos.

¡Muchas gracias!

Respuesta

19

Esto se consigue el SSN duplicado:

var duplicatedSSN = 
    from p in persons 
    group p by p.SSN into g 
    where g.Count() > 1 
    select g.Key; 

El la lista duplicada sería como:

var duplicated = persons.FindAll(p => duplicatedSSN.Contains(p.SSN)); 

Y luego simplemente itere sobre los duplicados y elimínelos.

duplicated.ForEach(dup => persons.Remove(dup)); 
+1

Su solución estaba cerca. La línea 'duplicated = persons.FindAll (duplicatedSSN.Contains (p => p.SSN);' no funcionó. Consulte mi respuesta para ver qué corregí para llegar a la respuesta. –

0

bien si implementa IComparable así:

int IComparable<Person>.CompareTo(Person person) 
{ 
    return this.SSN.CompareTo(person.SSN); 
} 

a continuación una comparación como el siguiente trabajo:

for (Int32 i = 0; i < people.Count; i++) 
{ 
    for (Int32 j = 1; j < items.Count; j++) 
    { 
     if (i != j && items[i] == items[j]) 
     { 
      // duplicate 
     } 
    } 
} 
0

Recorre la lista y mantén una Hashtable de SSN/count pairs. A continuación, enumerar su mesa y eliminar los elementos que coinciden con los SSN en cuenta SSN> 0.

Dictionary<string, int> ssnTable = new Dictionary<string, int>(); 

foreach (Person person in persons) 
{ 
    try 
    { 
     int count = ssnTable[person.SSN]; 
     count++; 
     ssnTable[person.SSN] = count; 
    } 
    catch(Exception ex) 
    { 
     ssnTable.Add(person.SSN, 1); 
    } 
} 

// traverse ssnTable here and remove items where value of entry (item count) > 1 
1
List<Person> actualPersons = persons.Distinct().ToList(); 
List<Person> duplicatePersons = persons.Except(actualPersons).ToList(); 
+1

Esto no funcionó porque Distinct mira todo de los datos. Solo quiero comparar SSN y buscar duplicados en ese campo. –

2

Gracias a gcores por iniciarme por un camino correcto. Esto es lo que terminé haciendo:

var duplicatedSSN = 
    from p in persons 
    group p by p.SSN into g 
    where g.Count() > 1 
    select g.Key; 

var duplicates = new List<Person>(); 

foreach (var dupeSSN in duplicatedSSN) 
{ 
    foreach (var person in persons.FindAll(p => p.SSN == dupeSSN)) 
     duplicates.Add(person); 
} 

duplicates.ForEach(dup => persons.Remove(dup)); 
+1

Disculpe, la línea era incorrecta. Debería haber dicho duplicated = persons.FindAll (p => duplicatedSSN.Contains (p.SSN)); . He editado la respuesta. – gcores

0

¿Se persons tiene que ser un List<Person>? ¿Y si fuera un Dictionary<int, Person>?

var persons = new Dictionary<int, Person>(); 

... 

// For each person you want to add to the list: 
var person = new Person 
{ 
    ... 
}; 

if (!persons.ContainsKey(person.SSN)) 
{ 
    persons.Add(person.SSN, person); 
} 

// If you absolutely, positively got to have a List: 
using System.Linq; 
List<Person> personsList = persons.Values.ToList(); 

Si está trabajando con instancias únicas de Person (en contraposición a las diferentes instancias que pueden ocurrirle a tener las mismas propiedades), es posible obtener un mejor rendimiento con un HashSet.

0

Según la recomendación de @gcores anterior.

Si desea agregar un solo objeto del duplicada SSN nuevo a la lista de personas, a continuación, añadir la siguiente línea:

IEnumerable<IGrouping<string, Person>> query = duplicated.GroupBy(d => d.SSN, d => d); 

     foreach (IGrouping<string, Person> duplicateGroup in query) 
     { 
      persons.Add(duplicateGroup .First()); 
     } 

Mi suposición aquí es que sólo se puede desear para eliminar valores duplicados menos el valor original del que derivaron los duplicados.

Cuestiones relacionadas