在对象列表中查找对象数据重复项

时间:2009-03-06 17:03:54

标签: c# .net

使用c#3和.Net Framework 3.5,我有一个Person对象

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

我有一个列表:

List<Person> persons = GetPersons();

如何在列表中SSN不唯一的人员中获取所有Person对象,并将其从人员列表中删除,并理想地将其添加到另一个名为“List<Person> dupes”的列表中?

原始列表可能如下所示:

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

最终结果是Cummings和Berra在原始人名单中,并且将Columbus和Steinbeck列入名为dupes的列表中。

非常感谢!

7 个答案:

答案 0 :(得分:23)

这可以获得重复的SSN:

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

重复列表如下:

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

然后迭代重复项并删除它们。

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

答案 1 :(得分:3)

感谢gcores帮助我开始了正确的道路。这就是我最终做的事情:

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

答案 2 :(得分:1)

List<Person> actualPersons = persons.Distinct().ToList();
List<Person> duplicatePersons = persons.Except(actualPersons).ToList();

答案 3 :(得分:1)

基于上述@gcores的推荐。

如果要将重复SSN的单个对象添加回人员列表,请添加以下行:

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

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

我的假设是你可能只想删除重复值减去重复项的原始值。

答案 4 :(得分:0)

如果你像这样实现IComparable:

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

然后进行如下比较:

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

答案 5 :(得分:0)

遍历列表并保留一个SSN /计数对的哈希表。然后枚举您的表并删除与SSN计数&gt;匹配的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

答案 6 :(得分:0)

persons必须是List<Person>吗?如果它是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();

如果您正在使用Person的唯一实例(而不是可能碰巧具有相同属性的不同实例),则使用HashSet可能会获得更好的性能。