2015-12-07 6 views
3

У меня есть класс с именем Customer, который имеет несколько строковых свойств, какУдалить дубликаты из массива объектов

firstName, lastName, email, etc. 

Я прочитал в информации о клиенте из csv файла, который создает массив класса:

Customer[] customers 

Мне нужно, чтобы удалили дубликатов клиентов с тем же адресом электронной почты, оставив только одну запись клиента для каждого конкретного адреса электронной почты.

Я сделал это, используя 2 контура, но это занимает почти 5 минут, так как обычно существует 50 000+ записей о клиентах. Как только я закончил удаление дубликатов, мне нужно записать информацию о клиенте в другой файл csv (здесь не нужна помощь).

Если я сделал Distinct в цикле, как бы удалить другие строковые переменные, которые являются частью класса для этого конкретного клиента?

Спасибо, Andrew

+0

ли идея запустить это ежедневно/еженедельно/раз в квартал? Частота этой задачи, скорее всего, будет определять постоянство решения. – mjw

+1

Distinct не будет работать для пользовательских типов без использования нового сопоставления равенства. используйте DistinctBy из MoreLinq. btw эта операция не займет много времени для 50 тыс. элементов, так как разный - это «O (n)» –

+0

. Моим выбором, вероятно, будет сортировка входного файла по дубликатному ключу (по электронной почте в вашем случае) и простейшее предыдущее сравнение текущего значения до добавляя к вашему объекту. – mjw

ответ

0

Я хотел бы сделать это следующим образом:

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("[email protected]", "Jon Mullen"); 
    testArr[1] = new Person("[email protected]", "Jane Cullen"); 
    testArr[2] = new Person("[email protected]", "Jon Cullen"); 
    testArr[3] = new Person("[email protected]", "John Mullen"); 
    testArr[4] = new Person("[email protected]", "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... 
     } 
5

с Linq, вы можете сделать это в O (N) времени (одноконтурный уровень) с GroupBy

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

Обновление

Немного о O(n) поведении GroupBy.

GroupBy реализуется в Linq (Enumerable.cs), так как это -

IEnumerable повторяется только один раз, чтобы создать группировку. A Hash предоставленного ключа (например, «Email» здесь) используется для поиска уникальных ключей, а элементы добавляются в Grouping, соответствующие ключам.

См. Этот код GetGrouping. И некоторые старые сообщения для справки.

Тогда Select, очевидно, является О (п) код, что делает приведенный выше код 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(); 
+0

* «Как Линк использует Reflection» * - У вас есть ссылка на это? –

+1

@Shnugo - LINQ не использует отражение. – Enigmativity

+0

Не могли бы вы рассказать нам, как вы знаете, что это будет выполняться в O (n)? –

Смежные вопросы