У кого-нибудь есть быстрый способ для удаления дубликатов общего списка на C#?Удалить дубликаты из списка <T> в C#
ответ
Возможно, вам следует рассмотреть возможность использования 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 }
*/
Сортируйте его, затем проверьте два и два рядом друг с другом, так как дубликаты будут сжиматься вместе.
Что-то вроде этого:
list.Sort();
Int32 index = 0;
while (index < list.Count - 1)
{
if (list[index] == list[index + 1])
list.RemoveAt(index);
else
index++;
}
В 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.
в C# это будет: Список
Если вы не заботитесь о порядке вы можете просто засунуть предметы в HashSet
, если вы сделать хотите сохранить заказ вы можете сделать что-то вроде этого:
var unique = new List<T>();
var hs = new HashSet<T>();
foreach (T t in list)
if (hs.Add(t))
unique.Add(t);
или Linq путь:
var hs = new HashSet<T>();
list.All(x => hs.Add(x));
Edit: метод HashSet
является O(N)
время и O(N)
пространства во время сортировки, а затем сделать уникальным (как су ggested от @lassevk и других) является O(N*lgN)
время и O(1)
пространство, так что это не так ясно для меня (как это было на первый взгляд), что сортировка путь уступает (мои извинения за временное вниз голосования ...)
Как насчет: -
var noDupes = list.Distinct().ToList();
In .net 3.5?
Если вы используете .Net 3+, вы можете использовать Linq.
List<T> withDupes = LoadSomeData();
List<T> noDupes = withDupes.Distinct().ToList();
Этот код не будет выполнен с ошибкой .Distinct() возвращает IEnumerable
Этот подход может использоваться только для списка с простыми значениями. – Polaris 2010-11-08 07:06:01
Нет, он работает со списками, содержащими объекты любого типа. Но вам придется переопределить сопоставитель по умолчанию для вашего типа. Например: public override bool Equals (object obj) {...} – BaBu 2010-12-09 14:27:49
Как говорится в kronoz .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;
}
Это может быть использовано для DeDupe любой коллекции и будет возвращать значения в исходном порядке.
Как правило, гораздо быстрее фильтровать коллекцию (как и Distinct()
, так и этот образец), чем было бы удалять элементы из нее.
Проблема с этим подходом состоит в том, что это O (N^2) -ish, в отличие от хэшета. Но, по крайней мере, очевидно, что он делает. – 2009-01-29 18:25:06
@DrJokepu - на самом деле я не понимал, что конструктор `HashSet` дедуплирован, что делает его лучше для большинства обстоятельств. Тем не менее, это сохранит порядок сортировки, который `HashSet` не делает. – Keith 2010-08-24 14:59:34
HashSet
Просто инициализировать HashSet со списком того же типа:
var noDupes = new HashSet<T>(withDupes);
Или, если вы хотите Список вернулся:
var noDupsList = new HashSet<T>(withDupes).ToList();
Метод расширения может быть достойной способ пойти ... примерно так:
public static List<T> Deduplicate<T>(this List<T> listToDeduplicate)
{
return listToDeduplicate.Distinct().ToList();
}
А потом называют, как это, например:
List<int> myFilteredList = unfilteredList.Deduplicate();
Другим способом в .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();
}
Вот метод расширения для удаления смежных дубликатов на месте. Сначала вызовите Сортировка() и перейдите в тот же IComparer. Это должно быть более эффективным, чем версия Lasse V. Karlsen, которая вызывает 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);
}
Есть много способов решить - вопрос дубликатов в списке, ниже один из них:
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
Вот простое решение, которое не требуется любое трудночитаемое 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
}
}
}
}
, который легче читать, чем Linq? – 2012-10-17 20:41:19
Может быть проще просто убедиться, что дубликаты не добавлены в список.
if(items.IndexOf(new_item) < 0)
items.add(new_item)
Я хотел бы использовать эту команду:
List<Store> myStoreList = Service.GetStoreListbyProvince(provinceId)
.GroupBy(s => s.City)
.Select(grp => grp.FirstOrDefault())
.OrderBy(s => s.City)
.ToList();
У меня есть эти поля в моем списке: Id, StoreName, Город, PostalCode Я хотел, чтобы показать список городов в раскрывающемся списке, который имеет дубликат значения. решение: выберите группу по городу, затем выберите первый список.
Надеюсь, это поможет :)
Это сработало для меня. просто используйте
List<Type> liIDs = liIDs.Distinct().ToList<Type>();
Замените «Тип» на нужный тип, например. внутр. Ответ
David J. является хорошим способом, нет необходимости в дополнительных объектов, сортировка и т.д. Это может быть улучшено на однако:
for (int innerIndex = items.Count - 1; innerIndex > outerIndex ; innerIndex--)
Таким образом, внешний контур идет сверху дно для весь список, но внутренний цикл идет снизу «до тех пор, пока не будет достигнуто положение внешнего контура».
Внешний цикл гарантирует, что весь список обработан, внутренний цикл находит фактические дубликаты, это может произойти только в той части, которая еще не обработана внешним контуром.
Или, если вы не хотите делать снизу вверх для внутреннего цикла вы могли бы начать внутреннюю петлю на outerIndex + 1.
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++;
}
}
}
В качестве вспомогательного метода (без Linq):
public static List<T> Distinct<T>(this List<T> list)
{
return (new HashSet<T>(list)).ToList();
}
Установка MoreLINQ пакета через NuGet, вы можете легко отчетливый список объектов по свойству
IEnumerable<Catalouge> distinctCatalouges = catalouges.DistinctBy(c => c.CatalougeCode);
Вы можете использовать союз
obj2 = obj1.Union(obj1).ToList();
Использовать Linq в Union метод.
Примечание: Это решение не требует знания Linq, кроме того, что оно существует.
Код
Сначала добавьте следующие строки в верхней части файла класса:
using System.Linq;
Теперь вы можете использовать следующие для удаления дубликатов из объекта называется, obj1
:
obj1 = obj1.Union(obj1).ToList();
Примечание: Переименовать obj1
на имя вашего объекта.
Как это работает
Союза списки команд одну из каждой записи двух исходных объектов. Поскольку obj1 - оба исходных объекта, это уменьшает obj1 до одной из каждой записи.
ToList()
возвращает новый список. Это необходимо, поскольку команды Linq, такие какUnion
, возвращают результат как результат IEnumerable вместо изменения исходного списка или возврата нового списка.
- 1. удалить дубликаты из списка <String[]>
- 2. Удалить дубликаты из списка <string> в C#
- 3. Удалить дубликаты из списка <int>
- 4. Удалить дубликаты из списка
- 5. C# удалить дубликаты из списка <string[]>
- 6. Удалить дубликаты из списка
- 7. удалить дубликаты из списка
- 8. удалить дубликаты из списка кортежей
- 9. Удалить дубликаты из списка Haskell
- 10. Как удалить дубликаты из списка C#
- 11. Удалить дубликаты подсписков из списка
- 12. Удалить дубликаты и оригинал из списка C#
- 13. Python. Удалить дубликаты элементов из списка списка
- 14. Удалить дубликаты из подпоследовательностей списка
- 15. Удалить дубликаты из раскрывающегося списка
- 16. Удалить дубликаты строк из списка
- 17. Python удалить дубликаты из списка?
- 18. Эликсир Удалить дубликаты из списка
- 19. Haskell Удалить дубликаты из списка
- 20. Удалить дубликаты значений из списка в Prolog
- 21. Удалить дубликаты из списка python
- 22. Удалить дубликаты из выпадающего списка
- 23. Как удалить дубликаты из списка в Clojure?
- 24. Удалить дубликаты из списка словарей
- 25. Как удалить дубликаты из списка?
- 26. Удалить дубликаты из списка списков
- 27. Удалить дубликаты из выпадающего списка
- 28. удалить дубликаты элементов из списка в python
- 29. Как удалить дубликаты из списка <object>
- 30. Удалить дубликаты объектов из списка нижестоящих <int>
Если я не ошибаюсь, большинство упомянутых выше подходов являются просто абстракциями этой самой процедуры, верно? Я бы взял ваш подход здесь, Лассе, потому что его, как я мысленно рисую, перемещаясь по данным. Но теперь меня интересуют различия в производительности между некоторыми предложениями. – 2009-08-11 20:52:47
Реализуйте их и время их, только чтобы быть уверенным. Даже нотация Big-O не поможет вам с фактическими показателями производительности, а только с отношением к эффекту роста. – 2009-08-12 07:03:30
Мне нравится этот подход, он более переносим на другие языки. – 2012-05-14 00:26:36