Najlepszy sposób na usunięcie zduplikowanych wartości ( NSString
) z NSMutableArray
Objective-C?
Czy to najłatwiejszy i właściwy sposób?
uniquearray = [[NSSet setWithArray:yourarray] allObjects];
ios
objective-c
nsmutablearray
Teo Choong Ping
źródło
źródło
Odpowiedzi:
Twoje
NSSet
podejście jest najlepsze, jeśli nie martwisz się o kolejność obiektów, ale z drugiej strony, jeśli nie martwisz się o kolejność, dlaczego nie przechowujesz ichNSSet
na początku?Napisałem odpowiedź poniżej w 2009 roku; w 2011 roku Apple dodał
NSOrderedSet
iOS 5 i Mac OS X 10.7. To, co kiedyś było algorytmem, to teraz dwa wiersze kodu:Jeśli martwisz się o kolejność i korzystasz z systemu iOS 4 lub starszego, wykonaj pętlę nad kopią tablicy:
źródło
[NSOrderedSet orderedSetWithArray:array];
Możesz następnie odzyskać tablicę przezarray = [orderedSet allObjects];
lub po prostu użyjNSOrderedSet
s zamiastNSArray
w pierwszej kolejności.[orderedSet allObjects]
z[orderedSet array]
!NSArray
i powinniśmy stworzyć tempNSMutableArray
. W twoim przykładzie pracujesz odwrotnieNSSet
) lub link @Simon Whitaker zapobiega przed dodaniem zduplikowanej wartości, co jest skutecznym sposobem?Wiem, że to stare pytanie, ale istnieje bardziej elegancki sposób usuwania duplikatów,
NSArray
jeśli nie zależy ci na zamówieniu .Jeśli użyjemy operatorów obiektów z Key Value Coding, możemy to zrobić:
Jak zauważył również AnthoPak , możliwe jest usuwanie duplikatów na podstawie właściwości. Przykładem może być:
@distinctUnionOfObjects.name
źródło
@distinctUnionOfObjects.property
do usuwania duplikatów według właściwości tablicy obiektów niestandardowych. Na przykład@distinctUnionOfObjects.name
Tak, używanie NSSet jest rozsądnym podejściem.
Aby dodać do odpowiedzi Jima Pulsa, oto alternatywne podejście do usuwania duplikatów przy zachowaniu porządku:
Jest to zasadniczo to samo podejście, co Jim's, ale kopiuje unikalne elementy do świeżej, zmiennej tablicy, zamiast usuwać duplikaty z oryginału. To sprawia, że jest nieco bardziej wydajna pamięciowo w przypadku dużej tablicy z dużą ilością duplikatów (nie ma potrzeby wykonywania kopii całej tablicy) i jest moim zdaniem trochę bardziej czytelna.
Zauważ, że w obu przypadkach sprawdzenie, czy element jest już uwzględniony w tablicy docelowej (używając
containsObject:
w moim przykładzie lubindexOfObject:inRange:
w Jim's), nie jest dobrze skalowane dla dużych tablic. Te testy są uruchamiane w czasie O (N), co oznacza, że jeśli podwoisz rozmiar oryginalnej tablicy, wykonanie każdego sprawdzenia potrwa dwa razy dłużej. Ponieważ sprawdzasz każdy obiekt w tablicy, będziesz także uruchamiać więcej tych droższych testów. Ogólny algorytm (zarówno mój, jak i Jima) działa w czasie O (N 2 ), co szybko staje się kosztowne, gdy oryginalna tablica rośnie.Aby sprowadzić to do czasu O (N), możesz użyć a
NSMutableSet
do przechowywania rekordu elementów już dodanych do nowej tablicy, ponieważ wyszukiwania NSSet mają wartość O (1) zamiast O (N). Innymi słowy, sprawdzenie, czy element jest członkiem zestawu NSSet, zajmuje tyle samo czasu, niezależnie od tego, ile elementów znajduje się w zestawie.Kod wykorzystujący to podejście wyglądałby mniej więcej tak:
To wciąż wydaje się trochę marnotrawne; nadal generujemy nową tablicę, gdy pytanie jasno wskazywało, że oryginalna tablica jest zmienna, więc powinniśmy być w stanie usunąć ją na miejscu i zaoszczędzić trochę pamięci. Coś takiego:
AKTUALIZACJA : Yuri Niyazov wskazał, że moja ostatnia odpowiedź faktycznie działa w czasie O (N 2 ), ponieważ
removeObjectAtIndex:
prawdopodobnie działa w czasie O (N).(Mówi „prawdopodobnie”, ponieważ nie wiemy na pewno, jak to zaimplementowano; ale jedną z możliwych implementacji jest to, że po usunięciu obiektu w indeksie X metoda przechodzi przez każdy element od indeksu X + 1 do ostatniego obiektu w tablicy , przenosząc je do poprzedniego indeksu. Jeśli tak jest, to rzeczywiście jest to wydajność O (N)).
Więc co robić? To zależy od sytuacji. Jeśli masz dużą tablicę i spodziewasz się tylko niewielkiej liczby duplikatów, funkcja de-duplikacji w miejscu będzie działać dobrze i pozwoli zaoszczędzić na tworzeniu zduplikowanej tablicy. Jeśli masz tablicę, w której spodziewasz się wielu duplikatów, prawdopodobnie najlepszym rozwiązaniem jest utworzenie oddzielnej, pozbawionej dupleksu tablicy. Wniosek jest taki, że notacja duże-O opisuje tylko charakterystykę algorytmu, a nie mówi ostatecznie, który jest najlepszy w danych okolicznościach.
źródło
Jeśli celujesz w iOS 5+ (który obejmuje cały świat iOS), najlepiej używać
NSOrderedSet
. Usuwa duplikaty i zachowuje kolejność plikówNSArray
.Po prostu zrób
Możesz teraz przekonwertować go z powrotem na unikalny NSArray
Lub po prostu użyć orderedSet ponieważ ma takie same metody jak NSArray podobnego
objectAtIndex:
,firstObject
i tak dalej.Sprawdzanie członkostwa w usłudze
contains
jest jeszcze szybszeNSOrderedSet
niż w przypadku domenyNSArray
Aby uzyskać więcej informacji, zapoznaj się z dokumentacją NSOrderedSet Reference
źródło
Dostępne w systemie OS X 10.7 i nowszych.
Jeśli martwisz się o zamówienie, właściwy sposób
Oto kod usuwania zduplikowanych wartości z NSArray w kolejności.
źródło
Potrzebujesz porządku
lub nie potrzebujesz zamówienia
źródło
Tutaj usunąłem zduplikowane wartości nazw z mainArray i zapisz wynik w NSMutableArray (listOfUsers)
źródło
Zwróć uwagę, że jeśli masz posortowaną tablicę, nie musisz sprawdzać każdego innego elementu w tablicy, tylko ostatni element. Powinno to być znacznie szybsze niż sprawdzanie wszystkich elementów.
Wygląda na to, że
NSOrderedSet
odpowiedzi, które również są sugerowane, wymagają dużo mniej kodu, ale jeśliNSOrderedSet
z jakiegoś powodu nie możesz użyć , a masz posortowaną tablicę, uważam, że moje rozwiązanie byłoby najszybsze. Nie jestem pewien, jak wypada to w porównaniu z szybkościąNSOrderedSet
rozwiązań. Zauważ również, że mój kod jest sprawdzanyisEqualToString:
, więc ta sama seria liter nie pojawi się więcej niż raz wnewArray
. Nie jestem pewien, czyNSOrderedSet
rozwiązania usuwają duplikaty na podstawie wartości lub lokalizacji w pamięci.Mój przykład zakłada, że
sortedSourceArray
zawiera tylkoNSString
s, tylkoNSMutableString
s lub ich połączenie. JeślisortedSourceArray
zamiast tego zawiera tylkoNSNumber
s lub tylkoNSDate
s, możesz zamienićz
i powinno działać idealnie. Jeśli
sortedSourceArray
zawiera kombinacjęNSString
s,NSNumber
s i / lubNSDate
s, prawdopodobnie ulegnie awarii.źródło
Istnieje operator obiektu KVC, który oferuje bardziej eleganckie rozwiązanie.
uniquearray = [yourarray valueForKeyPath:@"@distinctUnionOfObjects.self"];
Oto kategoria NSArray .źródło
Jeszcze jeden prosty sposób, który możesz wypróbować, który nie doda zduplikowanej wartości przed dodaniem obiektu do tablicy: -
// Załóżmy, że mutableArray jest przydzielona i zainicjowana oraz zawiera pewną wartość
źródło
Usuń zduplikowane wartości z NSMutableArray w Objective-C
źródło
Oto kod usuwania zduplikowanych wartości z NSMutable Array. . to będzie działać dla Ciebie. myArray to Twoja Mutable Array, z której chcesz usunąć zduplikowane wartości.
źródło
Użycie
Orderedset
wystarczy. Pozwoli to zachować usuwanie duplikatów z tablicy i zachować kolejność, której zestawy normalnie nie działająźródło
po prostu użyj tego prostego kodu:
ponieważ nsset nie zezwala na zduplikowane wartości i wszystkie obiekty zwracają tablicę
źródło
NSOrderedSet
insteed ofNSSet
.