2009-03-06 27 views
7

Sử dụng C# 3 và .Net Framework 3.5, tôi có một đối tượng PersonFind Duplicates dữ liệu đối tượng trong Danh sách đối tượng

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

và tôi đã có một danh sách trong số họ:

List<Person> persons = GetPersons(); 

thế nào Tôi có thể nhận được tất cả các đối tượng Người trong những người mà SSN không phải là duy nhất trong danh sách và loại bỏ chúng khỏi danh sách người và lý tưởng thêm chúng vào danh sách khác gọi là "List<Person> dupes"?

Danh sách ban đầu có thể trông như thế này:

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

Và kết quả cuối cùng sẽ phải Cummings và Berra trong danh sách những người ban đầu và sẽ phải Columbus và Steinbeck trong một danh sách gọi là giá trị nhân bản.

Rất cám ơn!

Trả lời

19

này được bạn SSN nhân đôi:

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

Các danh sách trùng lặp sẽ giống như:

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

Và sau đó chỉ cần lặp qua các mục trùng lặp và xóa chúng.

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

Giải pháp của bạn đã đóng. Dòng 'duplicated = persons.FindAll (duplicatedSSN.Contains (p => p.SSN); 'không hoạt động. Xem câu trả lời của tôi để xem những gì tôi đã sửa để có được câu trả lời –

0

tốt nếu bạn thực hiện IComparable như vậy:

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

sau đó so sánh như sau sẽ làm việc:

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

Traverse danh sách và giữ một Hashtable của cặp SSN/đếm. Sau đó, liệt kê bảng của bạn và loại bỏ các mục phù hợp với SSN nơi SSN đếm> 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

Điều này không có tác dụng Tôi chỉ muốn so sánh SSN và tìm kiếm sự phân chia trên trường đó –

2

Nhờ gcores cho việc tôi bắt đầu xuống một con đường đúng. Dưới đây là những gì tôi đã kết thúc:

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

Xin lỗi, dòng đã sai. Nó nên nói trùng lặp = people.FindAll (p => duplicatedSSN.Contains (p.SSN)); Tôi đã chỉnh sửa câu trả lời. – gcores

0

Cóphải là List<Person>? Nếu đó là Dictionary<int, Person> thì sao?

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

Nếu bạn đang làm việc với các trường hợp độc đáo của Person (như trái ngược với các trường hợp khác nhau có thể xảy ra để có tính chất tương tự), bạn có thể có được hiệu suất tốt hơn với một HashSet.

0

Dựa trên đề xuất của @gcores ở trên.

Nếu bạn muốn thêm một đối tượng duy nhất của trùng lặp SSN trở lại vào danh sách các người, sau đó thêm dòng sau:

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

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

giả định của tôi ở đây là bạn chỉ có thể muốn loại bỏ trùng lặp giá trị trừ giá trị ban đầu mà các bản sao xuất phát từ đó.

Các vấn đề liên quan