Удалить дубликаты из списка <T> в C #
496517 просмотра
25 ответа
14164 Репутация автора
У кого-нибудь есть быстрый способ дедупликации универсального списка в C #?
Автор: JC Grubbs Источник Размещён: 06.09.2008 07:15Ответы (25)
45 плюса
292148 Репутация автора
Сортируйте его, затем отметьте два и два рядом друг с другом, так как дубликаты будут объединяться.
Что-то вроде этого:
list.Sort();
Int32 index = 0;
while (index < list.Count - 1)
{
if (list[index] == list[index + 1])
list.RemoveAt(index);
else
index++;
}
Автор: Lasse Vågsæther Karlsen
Размещён: 06.09.2008 07:20
206 плюса
106844 Репутация автора
Возможно, вам следует рассмотреть возможность использования HashSet .
Из ссылки MSDN:
using System;
using System.Collections.Generic;
class Program
{
static void Main()
{
HashSet<int> evenNumbers = new HashSet<int>();
HashSet<int> oddNumbers = new HashSet<int>();
for (int i = 0; i < 5; i++)
{
// Populate numbers with just even numbers.
evenNumbers.Add(i * 2);
// Populate oddNumbers with just odd numbers.
oddNumbers.Add((i * 2) + 1);
}
Console.Write("evenNumbers contains {0} elements: ", evenNumbers.Count);
DisplaySet(evenNumbers);
Console.Write("oddNumbers contains {0} elements: ", oddNumbers.Count);
DisplaySet(oddNumbers);
// Create a new HashSet populated with even numbers.
HashSet<int> numbers = new HashSet<int>(evenNumbers);
Console.WriteLine("numbers UnionWith oddNumbers...");
numbers.UnionWith(oddNumbers);
Console.Write("numbers contains {0} elements: ", numbers.Count);
DisplaySet(numbers);
}
private static void DisplaySet(HashSet<int> set)
{
Console.Write("{");
foreach (int i in set)
{
Console.Write(" {0}", i);
}
Console.WriteLine(" }");
}
}
/* This example produces output similar to the following:
* evenNumbers contains 5 elements: { 0 2 4 6 8 }
* oddNumbers contains 5 elements: { 1 3 5 7 9 }
* numbers UnionWith oddNumbers...
* numbers contains 10 elements: { 0 2 4 6 8 1 3 5 7 9 }
*/
Автор: Jason Baker
Размещён: 06.09.2008 07:21
10 плюса
126798 Репутация автора
В Java (я предполагаю, что C # более или менее идентичен):
list = new ArrayList<T>(new HashSet<T>(list))
Если вы действительно хотите изменить исходный список:
List<T> noDupes = new ArrayList<T>(new HashSet<T>(list));
list.clear();
list.addAll(noDupes);
Чтобы сохранить порядок, просто замените HashSet на LinkedHashSet.
Автор: Tom Hawtin - tackline Размещён: 06.09.2008 07:295 плюса
74309 Репутация автора
Если вы не заботитесь о порядке вы можете просто засунуть элементы в HashSet
, если вы действительно хотите сохранить заказ вы можете сделать что - то вроде этого:
var unique = new List<T>();
var hs = new HashSet<T>();
foreach (T t in list)
if (hs.Add(t))
unique.Add(t);
Или Линк путь:
var hs = new HashSet<T>();
list.All( x => hs.Add(x) );
Edit:HashSet
метод O(N)
времени и O(N)
пространства во время сортировки , а затем сделать уникальный (как это было предложено @ lassevk и других) есть O(N*lgN)
время и O(1)
пространство , так что это не так ясно для меня (как это было на первый взгляд) , что сортировка путь уступает (мой извиняюсь за временное отрицательное голосование ...)
137 плюса
25518 Репутация автора
Как насчет:-
var noDupes = list.Distinct().ToList();
В .net 3.5?
Автор: ljs Размещён: 06.09.2008 07:56729 плюса
19899 Репутация автора
Если вы используете .Net 3+, вы можете использовать Linq.
List<T> withDupes = LoadSomeData();
List<T> noDupes = withDupes.Distinct().ToList();
Автор: Factor Mystic
Размещён: 06.09.2008 07:56
22 плюса
94210 Репутация автора
Как сказал кроноз в .Net 3.5 вы можете использовать Distinct()
.
В .Net 2 вы можете имитировать это:
public IEnumerable<T> DedupCollection<T> (IEnumerable<T> input)
{
var passedValues = new HashSet<T>();
// Relatively simple dupe check alg used as example
foreach(T item in input)
if(passedValues.Add(item)) // True if item is new
yield return item;
}
Это может быть использовано для дедупликации любой коллекции и будет возвращать значения в исходном порядке.
Обычно фильтровать коллекцию гораздо быстрее (как Distinct()
и в этом примере), чем удалять из нее элементы.
85 плюса
21009 Репутация автора
Просто инициализируйте HashSet списком того же типа:
var noDupes = new HashSet<T>(withDupes);
Или, если вы хотите вернуть список:
var noDupsList = new HashSet<T>(withDupes).ToList();
Автор: Even Mien
Размещён: 24.11.2009 08:05
12 плюса
121 Репутация автора
Метод расширения может быть приличным способом ... что-то вроде этого:
public static List<T> Deduplicate<T>(this List<T> listToDeduplicate)
{
return listToDeduplicate.Distinct().ToList();
}
А потом позвоните вот так, например:
List<int> myFilteredList = unfilteredList.Deduplicate();
Автор: Geoff Taylor
Размещён: 03.04.2010 01:05
1 плюс
19 Репутация автора
Еще один способ в .Net 2.0
static void Main(string[] args)
{
List<string> alpha = new List<string>();
for(char a = 'a'; a <= 'd'; a++)
{
alpha.Add(a.ToString());
alpha.Add(a.ToString());
}
Console.WriteLine("Data :");
alpha.ForEach(delegate(string t) { Console.WriteLine(t); });
alpha.ForEach(delegate (string v)
{
if (alpha.FindAll(delegate(string t) { return t == v; }).Count > 1)
alpha.Remove(v);
});
Console.WriteLine("Unique Result :");
alpha.ForEach(delegate(string t) { Console.WriteLine(t);});
Console.ReadKey();
}
Автор: Bhasin
Размещён: 10.02.2011 06:55
5 плюса
384 Репутация автора
Вот метод расширения для удаления соседних дубликатов на месте. Сначала вызовите Sort () и передайте в тот же IComparer. Это должно быть более эффективно, чем версия Лассе В. Карлсена, в которой неоднократно вызывается RemoveAt (что приводит к перемещению памяти из нескольких блоков).
public static void RemoveAdjacentDuplicates<T>(this List<T> List, IComparer<T> Comparer)
{
int NumUnique = 0;
for (int i = 0; i < List.Count; i++)
if ((i == 0) || (Comparer.Compare(List[NumUnique - 1], List[i]) != 0))
List[NumUnique++] = List[i];
List.RemoveRange(NumUnique, List.Count - NumUnique);
}
Автор: gary
Размещён: 25.02.2011 06:15
1 плюс
11 Репутация автора
Есть много способов решить - проблема с дубликатами в списке, ниже один из них:
List<Container> containerList = LoadContainer();//Assume it has duplicates
List<Container> filteredList = new List<Container>();
foreach (var container in containerList)
{
Container duplicateContainer = containerList.Find(delegate(Container checkContainer)
{ return (checkContainer.UniqueId == container.UniqueId); });
//Assume 'UniqueId' is the property of the Container class on which u r making a search
if(!containerList.Contains(duplicateContainer) //Add object when not found in the new class object
{
filteredList.Add(container);
}
}
Ура Рави Ганесан
Автор: Ravi Ganesan Размещён: 10.04.2011 05:021 плюс
21 Репутация автора
Вот простое решение, которое не требует трудно читаемого LINQ или какой-либо предварительной сортировки списка.
private static void CheckForDuplicateItems(List<string> items)
{
if (items == null ||
items.Count == 0)
return;
for (int outerIndex = 0; outerIndex < items.Count; outerIndex++)
{
for (int innerIndex = 0; innerIndex < items.Count; innerIndex++)
{
if (innerIndex == outerIndex) continue;
if (items[outerIndex].Equals(items[innerIndex]))
{
// Duplicate Found
}
}
}
}
Автор: David J.
Размещён: 14.02.2012 12:20
3 плюса
49 Репутация автора
Может быть проще просто убедиться, что дубликаты не добавляются в список.
if(items.IndexOf(new_item) < 0)
items.add(new_item)
Автор: Chris
Размещён: 29.06.2012 02:33
26 плюса
456 Репутация автора
Мне нравится использовать эту команду:
List<Store> myStoreList = Service.GetStoreListbyProvince(provinceId)
.GroupBy(s => s.City)
.Select(grp => grp.FirstOrDefault())
.OrderBy(s => s.City)
.ToList();
У меня есть эти поля в моем списке: Id, StoreName, City, PostalCode Я хотел показать список городов в выпадающем списке, который имеет повторяющиеся значения. Решение: сгруппируйте по городам, затем выберите первый в списке.
Я надеюсь, что это помогает :)
Автор: Eric Размещён: 27.07.2012 06:5730 плюса
451 Репутация автора
Это сработало для меня. просто используйте
List<Type> liIDs = liIDs.Distinct().ToList<Type>();
Замените «Тип» на желаемый тип, например, int.
Автор: Hossein Sarshar Размещён: 15.11.2012 06:511 плюс
11 Репутация автора
Ответ Дэвида Дж. - хороший метод, не требующий дополнительных объектов, сортировки и т. Д. Однако его можно улучшить:
for (int innerIndex = items.Count - 1; innerIndex > outerIndex ; innerIndex--)
Таким образом, внешний цикл идет сверху вниз для всего списка, но внутренний цикл идет снизу «до тех пор, пока не будет достигнута позиция внешнего цикла».
Внешний цикл гарантирует, что весь список обработан, внутренний цикл находит фактические дубликаты, они могут происходить только в той части, которую внешний цикл еще не обработал.
Или, если вы не хотите делать восходящий цикл для внутреннего цикла, вы можете запустить внутренний цикл в externalIndex + 1.
Автор: Guest Размещён: 22.10.2013 11:101 плюс
558 Репутация автора
public static void RemoveDuplicates<T>(IList<T> list )
{
if (list == null)
{
return;
}
int i = 1;
while(i<list.Count)
{
int j = 0;
bool remove = false;
while (j < i && !remove)
{
if (list[i].Equals(list[j]))
{
remove = true;
}
j++;
}
if (remove)
{
list.RemoveAt(i);
}
else
{
i++;
}
}
}
Автор: Paul Richards
Размещён: 14.05.2014 11:11
5 плюса
569 Репутация автора
В качестве вспомогательного метода (без Linq):
public static List<T> Distinct<T>(this List<T> list)
{
return (new HashSet<T>(list)).ToList();
}
Автор: Grant
Размещён: 18.11.2014 09:45
3 плюса
638 Репутация автора
Установив пакет MoreLINQ через Nuget, вы можете легко различать список объектов по свойству
IEnumerable<Catalogue> distinctCatalogues = catalogues.DistinctBy(c => c.CatalogueCode);
Автор: dush88c
Размещён: 15.03.2017 02:51
1 плюс
27 Репутация автора
Вы можете использовать Союз
obj2 = obj1.Union(obj1).ToList();
Автор: flagamba
Размещён: 06.08.2017 03:16
6 плюса
5276 Репутация автора
Используйте метод Linq's Union .
Примечание. Это решение не требует никаких знаний о Linq, кроме того, что оно существует.
Код
Начните с добавления следующего в начало вашего файла классов:
using System.Linq;
Теперь вы можете использовать следующее для удаления дубликатов из объекта с именем obj1
:
obj1 = obj1.Union(obj1).ToList();
Примечание: переименуйте obj1
в название вашего объекта.
Как это устроено
Команда Union перечисляет одну из каждой записи двух исходных объектов. Поскольку obj1 - оба исходных объекта, это сводит obj1 к одной из каждой записи.
В
ToList()
возвращает новый список. Это необходимо, потому что команды Linq likeUnion
возвращают результат как результат IEnumerable вместо изменения исходного списка или возврата нового списка.
1 плюс
47 Репутация автора
Простая интуитивно понятная реализация:
public static List<PointF> RemoveDuplicates(List<PointF> listPoints)
{
List<PointF> result = new List<PointF>();
for (int i = 0; i < listPoints.Count; i++)
{
if (!result.Contains(listPoints[i]))
result.Add(listPoints[i]);
}
return result;
}
Автор: Moctar Haiz
Размещён: 19.04.2018 09:05
1 плюс
131 Репутация автора
Если у вас есть классы буксирных Product
и Customer
мы хотим , чтобы удалить повторяющиеся элементы из своего списка
public class Product
{
public int Id { get; set; }
public string ProductName { get; set; }
}
public class Customer
{
public int Id { get; set; }
public string CustomerName { get; set; }
}
Вы должны определить общий класс в форме ниже
public class ItemEqualityComparer<T> : IEqualityComparer<T> where T : class
{
private readonly PropertyInfo _propertyInfo;
public ItemEqualityComparer(string keyItem)
{
_propertyInfo = typeof(T).GetProperty(keyItem, BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.Public);
}
public bool Equals(T x, T y)
{
var xValue = _propertyInfo?.GetValue(x, null);
var yValue = _propertyInfo?.GetValue(y, null);
return xValue != null && yValue != null && xValue.Equals(yValue);
}
public int GetHashCode(T obj)
{
var propertyValue = _propertyInfo.GetValue(obj, null);
return propertyValue == null ? 0 : propertyValue.GetHashCode();
}
}
Затем вы можете удалить дубликаты в вашем списке.
var products = new List<Product>
{
new Product{ProductName = "product 1" ,Id = 1,},
new Product{ProductName = "product 2" ,Id = 2,},
new Product{ProductName = "product 2" ,Id = 4,},
new Product{ProductName = "product 2" ,Id = 4,},
};
var productList = products.Distinct(new ItemEqualityComparer<Product>(nameof(Product.Id))).ToList();
var customers = new List<Customer>
{
new Customer{CustomerName = "Customer 1" ,Id = 5,},
new Customer{CustomerName = "Customer 2" ,Id = 5,},
new Customer{CustomerName = "Customer 2" ,Id = 5,},
new Customer{CustomerName = "Customer 2" ,Id = 5,},
};
var customerList = customers.Distinct(new ItemEqualityComparer<Customer>(nameof(Customer.Id))).ToList();
этот код удаление дубликатов детали , Id
если вы хотите удалить повторяющиеся элементы от другого имущества, вы можете изменить то nameof(YourClass.DuplicateProperty)
же nameof(Customer.CustomerName)
затем удалить повторяющиеся элементы по CustomerName
недвижимости.
0 плюса
1 Репутация автора
Это берет различные элементы без дублирования элементов и снова преобразует их в список.
List myNoneDuplicateValue = listValueWithDuplicate.Distinct (). ToList ();
Автор: Alfred Udah Размещён: 13.03.2019 10:58Вопросы из категории :
- c# Преобразовать десятичную в двойную?
- c# Как рассчитать чей-то возраст в C #?
- c# Как вы сортируете словарь по значению?
- c# В чем разница между int и Integer в Java и C #?
- c# Как создать новый экземпляр объекта из Типа
- list Функция транспонирования / распаковки (обратная сторона zip)?
- list How would you make a comma-separated string from a list of strings?
- list Удалить дубликаты из списка <T> в C #
- list Console.WriteLine и общий список
- list Как проверить, если список пуст?
- generics Почему в C # нельзя хранить объект List <string> в переменной List <object>
- generics Преобразование общего типа из строки
- generics Лучший способ проверить, является ли универсальный тип строкой? (С #)
- generics Есть ли ограничение, которое ограничивает мой общий метод численными типами?
- generics Каковы различия между «универсальными» типами в C ++ и Java?
- duplicates Как удалить дубликаты из массива C #?
- duplicates Как я могу удалить дубликаты строк?
- duplicates Как удалить повторяющиеся элементы из ArrayList?
- duplicates Дублирование экземпляров модели и связанных с ними объектов в Django / Algorithm для повторного дублирования объекта