Фильтр дубликатов из списка - PullRequest
4 голосов
/ 07 февраля 2011

у меня List<Location> locations.

Класс Location имеет свойство Coordinates - предполагается строка.

Как я могу удалить местоположения с дублирующимися координатами и поместить их в отдельный список? Наличие двух списков - один для дубликатов и один без.

Ответы [ 2 ]

4 голосов
/ 07 февраля 2011

Создание IEqualityComparer будет одной из ваших первых задач (которая позволяет сравнивать объекты на основе выбранных вами свойств).

Если вы хотите получать уникальные предметы с помощью Linq, вы можете использовать метод Distinct ().

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

var distinctObjects = originalList.Distinct();
var duplicateList = originalList.Except(distinctObjects);

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

3 голосов
/ 07 февраля 2011

Это зависит от того, что вы имеете в виду, на самом деле. Если вам нужен один представительский список и еще один для оставшихся дубликатов, вы можете сделать:

var locationsByCoordinates = locations.ToLookup(location => location.Coordinates);

var distinct = locationsByCoordinates.Select(group => group.First())
                                     .ToList();

var duplicates = locationsByCoordinates.SelectMany(group => group.Skip(1))
                                       .ToList(); 

С другой стороны, если вы хотите один список для тех уникальных предметов, а другой для тех, которые не являются:

var distinct = locationsByCoordinates.Where(group => group.Count() == 1)
                                     .Select(group => group.Single())
                                     .ToList();

var duplicates = locationsByCoordinates.Where(group => group.Count() != 1)
                                       .SelectMany(group => group)
                                       .ToList();

Это немного неэффективно, так как он перечисляет поиск дважды. Чуть лучше было бы что-то вроде:

var distinct = new List<Location>();
var duplicates = new List<Location>();

foreach(var group in locationsByCoordinates)
{
    var target = group.Count() == 1 ? distinct : duplicates;
    target.AddRange(group);
}
...