Czy ktoś ma szybką metodę usuwania duplikatów ogólnej listy w C #?
c#
list
generics
duplicates
JC Grubbs
źródło
źródło
ICollection<MyClass> withoutDuplicates = new HashSet<MyClass>(inputList);
Odpowiedzi:
Być może powinieneś rozważyć użycie HashSet .
Z linku MSDN:
źródło
HashSet
nie ma indeksu , dlatego nie zawsze można go używać. Raz muszę stworzyć ogromną listę bez duplikatów, a następnie użyć jejListView
w trybie wirtualnym. Bardzo szybko było zrobićHashSet<>
pierwszy, a następnie przekształcić go wList<>
(dzięki czemuListView
można uzyskać dostęp do przedmiotów według indeksu).List<>.Contains()
jest zbyt wolny.Jeśli używasz .Net 3+, możesz użyć Linq.
źródło
Co powiesz na:
W .net 3.5?
źródło
Po prostu zainicjuj zestaw HashSet za pomocą listy tego samego typu:
Lub, jeśli chcesz zwrócić listę:
źródło
List<T>
wyniku, użyjnew HashSet<T>(withDupes).ToList()
Posortuj, a następnie zaznacz dwa i dwa obok siebie, ponieważ duplikaty będą się zlepiać.
Coś takiego:
Uwagi:
źródło
RemoveAt
jest bardzo kosztowną operacją naList
Lubię używać tego polecenia:
Mam na liście następujące pola: Id, StoreName, City, PostalCode Chciałem wyświetlić listę miast w menu, które ma zduplikowane wartości. rozwiązanie: Grupuj według miasta, a następnie wybierz pierwszą z listy.
Mam nadzieję, że to pomoże :)
źródło
To zadziałało dla mnie. po prostu użyj
Zamień „Type” na żądany typ, np. Int.
źródło
Jak powiedział kronoz w .Net 3.5, możesz używać
Distinct()
.W .Net 2 możesz to naśladować:
Można to wykorzystać do deduplikacji dowolnej kolekcji i zwróci wartości w oryginalnej kolejności.
Zazwyczaj filtrowanie kolekcji jest znacznie szybsze (tak jak w przypadku
Distinct()
tej i tej próbki), niż usuwanie jej z niej.źródło
HashSet
konstruktor się poświęcił, co czyni go lepszym w większości przypadków. Zachowałoby to jednak porządek sortowania, czegoHashSet
nie robi.Dictionary<T, object>
zamiast wymienić.Contains
z.ContainsKey
i.Add(item)
z.Add(item, null)
HashSet
zachowuje porządek, podczas gdyDistinct()
nie.Metoda rozszerzenia może być dobrym sposobem ... coś takiego:
A potem zadzwoń w ten sposób, na przykład:
źródło
W Javie (zakładam, że C # jest mniej więcej identyczny):
Jeśli naprawdę chcesz zmutować oryginalną listę:
Aby zachować porządek, po prostu zamień HashSet na LinkedHashSet.
źródło
var noDupes = new HashSet<T>(list); list.Clear(); list.AddRange(noDupes);
:)Spowoduje to rozróżnienie (elementy bez powielania elementów) i ponowne przekonwertowanie go na listę:
źródło
Uwaga: To rozwiązanie nie wymaga znajomości Linq, poza tym, że istnieje.
Kod
Zacznij od dodania następujących elementów na początku pliku zajęć:
Teraz możesz użyć następujących poleceń, aby usunąć duplikaty z obiektu o nazwie
obj1
:Uwaga: Zmień nazwę
obj1
na nazwę swojego obiektu.Jak to działa
Polecenie Union wyświetla jeden z każdego wpisu dwóch obiektów źródłowych. Ponieważ obj1 jest oboma obiektami źródłowymi, redukuje obj1 do jednego z każdego wpisu.
ToList()
Zwraca nową listę. Jest to konieczne, ponieważ polecenia Linq, takie jakUnion
zwraca wynik jako wynik IEnumerable zamiast modyfikować oryginalną Listę lub zwracać nową Listę.źródło
Jako metoda pomocnicza (bez Linq):
źródło
Jeśli nie dbają o porządek można po prostu wsadzić elementy do
HashSet
, jeśli nie chcesz, aby utrzymać porządek można zrobić coś takiego:Lub sposób Linq:
Edit:
HashSet
metoda jestO(N)
czas iO(N)
miejsce podczas sortowania a następnie podejmowania wyjątkowy (jak sugeruje @ lassevk i innych) jestO(N*lgN)
czas iO(1)
przestrzeń, więc to nie jest tak oczywiste dla mnie (jak to było na pierwszy rzut oka), że sposób sortowania jest gorszy (moja przepraszam za tymczasowe głosowanie w dół ...)źródło
Oto metoda rozszerzenia służąca do usuwania sąsiadujących duplikatów na miejscu. Najpierw wywołaj Sort () i przekaż ten sam IComparer. Powinno to być bardziej wydajne niż wersja Lasse V. Karlsena, która wielokrotnie wywołuje RemoveAt (co powoduje wiele ruchów pamięci bloków).
źródło
Instalując pakiet MoreLINQ za pośrednictwem Nuget, możesz łatwo odróżnić listę obiektów według właściwości
źródło
Łatwiej może być po prostu upewnienie się, że duplikaty nie zostaną dodane do listy.
źródło
List<T>.Contains
metody za każdym razem, ale z ponad 1 000 000 wpisów. Ten proces spowalnia moją aplikację.List<T>.Distinct().ToList<T>()
Zamiast tego używam pierwszego.Możesz użyć Union
źródło
Kolejny sposób w .Net 2.0
źródło
Istnieje wiele sposobów rozwiązania - problem duplikatów na liście, poniżej jest jednym z nich:
Pozdrawiam Ravi Ganesan
źródło
Oto proste rozwiązanie, które nie wymaga trudnego do odczytania LINQ ani żadnego wcześniejszego sortowania listy.
źródło
Odpowiedź Davida J. jest dobrą metodą, nie wymaga dodatkowych obiektów, sortowania itp. Można ją jednak ulepszyć:
for (int innerIndex = items.Count - 1; innerIndex > outerIndex ; innerIndex--)
Tak więc zewnętrzna pętla znajduje się u góry na dole dla całej listy, ale wewnętrzna pętla jest na dole „aż do osiągnięcia pozycji zewnętrznej pętli”.
Zewnętrzna pętla zapewnia, że cała lista jest przetwarzana, wewnętrzna pętla znajduje rzeczywiste duplikaty, mogą się one zdarzyć tylko w części, której zewnętrzna pętla jeszcze nie przetworzyła.
Lub jeśli nie chcesz robić oddolnej pętli wewnętrznej, możesz rozpocząć pętlę wewnętrzną od outerIndex + 1.
źródło
Wszystkie odpowiedzi kopiują listy, tworzą nową listę, używają wolnych funkcji lub są po prostu boleśnie powolne.
Według mnie jest to najszybsza i najtańsza metoda, jaką znam (wspierana przez bardzo doświadczonego programistę specjalizującego się w optymalizacji fizyki w czasie rzeczywistym).
Ostateczny koszt to:
nlogn + n + nlogn = n + 2nlogn = O (nlogn), co jest całkiem miłe.
Uwaga na temat RemoveRange: Ponieważ nie możemy ustawić liczby na liście i uniknąć korzystania z funkcji Usuń, nie znam dokładnie szybkości tej operacji, ale myślę, że jest to najszybszy sposób.
źródło
Jeśli masz zajęcia holownicze
Product
iCustomer
chcemy usunąć zduplikowane elementy z ich listyMusisz zdefiniować klasę ogólną w poniższym formularzu
następnie możesz usunąć zduplikowane elementy z listy.
ten kod usunąć zduplikowane pozycje wg
Id
jeśli chcesz usunąć duplikaty przez inne właściwości, można zmienićnameof(YourClass.DuplicateProperty)
samnameof(Customer.CustomerName)
potem usunąć duplikaty przezCustomerName
Property.źródło
źródło
Prosta intuicyjna implementacja:
źródło