繁体   English   中英

从对象数组中删除重复项

[英]Remove duplicates from array of objects

我有一个名为Customer的类,它有几个字符串属性

firstName, lastName, email, etc.  

我从csv文件中读取客户信息,该文件创建了该类的数组:

Customer[] customers  

我需要删除具有相同电子邮件地址的重复客户,每个特定电子邮件地址只留下1个客户记录。

我使用2个循环完成了这项工作,但由于通常有50,000多个客户记录,因此需要将近5分钟。 完成删除重复项后,我需要将客户信息写入另一个csv文件(此处无需帮助)。

如果我在循环中做了一个Distinct ,我如何删除作为该特定客户的类的一部分的其他字符串变量?

谢谢,安德鲁

使用Linq ,您可以使用GroupBy在O(n)时间(单级循环)中执行此操作

var uniquePersons = persons.GroupBy(p => p.Email)
                           .Select(grp => grp.First())
                           .ToArray();

更新

关于GroupBy O(n)行为。

GroupByLinqEnumerable.cs )中实现,因为 -

IEnumerable仅迭代一次以创建分组。 提供的密钥的Hash (例如,这里的“电子邮件”)用于查找唯一密钥,并且元素被添加到与密钥对应的Grouping

请参阅此GetGrouping代码。 还有一些旧帖子可供参考。

然后Select显然是一个O(n)代码,整体上面的代码为O(n)

更新2

处理empty / null值。

因此,如果存在Email值为null或为empty实例,则简单的GroupBy将仅从null取出其中一个对象并empty每个对象。

将所有具有null / empty值的对象包含在内的一种快速方法是在运行时为这些对象使用一些唯一键,例如

var tempEmailIndex = 0;
var uniqueNullAndEmpty = persons
                         .GroupBy(p => string.IsNullOrEmpty(p.Email) 
                                       ? (++tempEmailIndex).ToString() : p.Email)
                         .Select(grp => grp.First())
                         .ToArray();

我这样做:

public class Person {
    public Person(string eMail, string Name) {
        this.eMail = eMail;
        this.Name = Name;
    }
    public string eMail { get; set; }
    public string Name { get; set; }
}
public class eMailKeyedCollection : System.Collections.ObjectModel.KeyedCollection<string, Person> {
    protected override string GetKeyForItem(Person item) {
        return item.eMail;
    }
}

public void testIt() {
    var testArr = new Person[5];
    testArr[0] = new Person("Jon@Mullen.com", "Jon Mullen");
    testArr[1] = new Person("Jane@Cullen.com", "Jane Cullen");
    testArr[2] = new Person("Jon@Cullen.com", "Jon Cullen");
    testArr[3] = new Person("John@Mullen.com", "John Mullen");
    testArr[4] = new Person("Jon@Mullen.com", "Test Other"); //same eMail as index 0...

    var targetList = new eMailKeyedCollection();
    foreach (var p in testArr) {
        if (!targetList.Contains(p.eMail))
            targetList.Add(p);
    }
}

如果在集合中找到该项目,您可以使用以下方法轻松选择(并最终修改)它:

        if (!targetList.Contains(p.eMail))
            targetList.Add(p);
        else {
           var currentPerson=targetList[p.eMail];
           //modify Name, Address whatever... 
        }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM