Der beste Weg, um doppelte Werte ( NSString) aus NSMutableArrayObjective-C zu entfernen ?
Ist dies der einfachste und richtige Weg?
uniquearray = [[NSSet setWithArray:yourarray] allObjects];
Der beste Weg, um doppelte Werte ( NSString) aus NSMutableArrayObjective-C zu entfernen ?
Ist dies der einfachste und richtige Weg?
uniquearray = [[NSSet setWithArray:yourarray] allObjects];
Antworten:
Ihr NSSetAnsatz ist der beste, wenn Sie sich keine Sorgen um die Reihenfolge der Objekte machen. Wenn Sie sich jedoch keine Sorgen um die Reihenfolge machen, warum speichern Sie sie dann nicht zunächst in einer NSSet?
Ich habe die Antwort unten 2009 geschrieben. Im Jahr 2011 fügte Apple NSOrderedSetiOS 5 und Mac OS X 10.7 hinzu. Was früher ein Algorithmus war, besteht jetzt aus zwei Codezeilen:
NSOrderedSet *orderedSet = [NSOrderedSet orderedSetWithArray:yourArray];
NSArray *arrayWithoutDuplicates = [orderedSet array];
Wenn Sie sich über die Reihenfolge Sorgen machen und iOS 4 oder früher verwenden, durchlaufen Sie eine Kopie des Arrays:
NSArray *copy = [mutableArray copy];
NSInteger index = [copy count] - 1;
for (id object in [copy reverseObjectEnumerator]) {
if ([mutableArray indexOfObject:object inRange:NSMakeRange(0, index)] != NSNotFound) {
[mutableArray removeObjectAtIndex:index];
}
index--;
}
[copy release];
[NSOrderedSet orderedSetWithArray:array];Sie einfach. Sie können dann ein Array über zurückholen array = [orderedSet allObjects];oder einfach NSOrderedSets anstelle von s verwenden NSArray.
[orderedSet allObjects]mit [orderedSet array]!
NSArrayund sollten normalerweise Temp schaffen NSMutableArray. In Ihrem Beispiel arbeiten Sie umgekehrt
NSSetWeiß jemand, welche Ansicht am besten geeignet ist, um Duplikate zu entfernen ? Ist diese Methode (mit ) oder der @ Simon Whitaker- Link zu verhindern, bevor Duplikate hinzugefügt werden?
Ich weiß, dass dies eine alte Frage ist, aber es gibt eine elegantere Möglichkeit, Duplikate in einem zu entfernen, NSArray wenn Sie sich nicht für die Reihenfolge interessieren .
Wenn wir Objektoperatoren aus der Schlüsselwertcodierung verwenden , können wir dies tun:
uniquearray = [yourarray valueForKeyPath:@"@distinctUnionOfObjects.self"];
Wie AnthoPak ebenfalls feststellte, ist es möglich, Duplikate basierend auf einer Eigenschaft zu entfernen. Ein Beispiel wäre:@distinctUnionOfObjects.name
@distinctUnionOfObjects.property, um Duplikate nach Eigenschaften eines Arrays benutzerdefinierter Objekte zu entfernen. Zum Beispiel@distinctUnionOfObjects.name
Ja, die Verwendung von NSSet ist ein sinnvoller Ansatz.
Um die Antwort von Jim Puls zu ergänzen, gibt es hier einen alternativen Ansatz zum Entfernen von Duplikaten unter Beibehaltung der Reihenfolge:
// Initialise a new, empty mutable array
NSMutableArray *unique = [NSMutableArray array];
for (id obj in originalArray) {
if (![unique containsObject:obj]) {
[unique addObject:obj];
}
}
Es ist im Wesentlichen der gleiche Ansatz wie bei Jim, kopiert jedoch eindeutige Elemente in ein neues veränderbares Array, anstatt Duplikate aus dem Original zu löschen. Dies macht es etwas speichereffizienter bei einem großen Array mit vielen Duplikaten (es ist nicht erforderlich, eine Kopie des gesamten Arrays zu erstellen) und ist meiner Meinung nach etwas lesbarer.
Beachten Sie, dass in beiden Fällen die Überprüfung, ob ein Element bereits im Zielarray enthalten ist ( containsObject:in meinem Beispiel oder indexOfObject:inRange:in Jims), für große Arrays nicht gut skalierbar ist. Diese Überprüfungen werden in O (N) -Zeit ausgeführt. Wenn Sie also die Größe des ursprünglichen Arrays verdoppeln, dauert die Ausführung jeder Überprüfung doppelt so lange. Da Sie die Prüfung für jedes Objekt im Array durchführen, führen Sie auch mehr dieser teureren Prüfungen durch. Der Gesamtalgorithmus (sowohl meiner als auch Jims) läuft in O (N 2 ) -Zeit, was schnell teuer wird, wenn das ursprüngliche Array wächst.
Um dies auf O (N) Zeit zu NSMutableSetreduzieren, können Sie mit a einen Datensatz von Elementen speichern, die bereits zum neuen Array hinzugefügt wurden, da NSSet-Lookups O (1) und nicht O (N) sind. Mit anderen Worten, die Überprüfung, ob ein Element Mitglied eines NSSet ist, dauert unabhängig von der Anzahl der Elemente in der Gruppe dieselbe Zeit.
Code, der diesen Ansatz verwendet, würde ungefähr so aussehen:
NSMutableArray *unique = [NSMutableArray array];
NSMutableSet *seen = [NSMutableSet set];
for (id obj in originalArray) {
if (![seen containsObject:obj]) {
[unique addObject:obj];
[seen addObject:obj];
}
}
Dies scheint jedoch immer noch ein wenig verschwenderisch; Wir generieren immer noch ein neues Array, wenn die Frage klarstellt, dass das ursprüngliche Array veränderbar ist. Daher sollten wir in der Lage sein, es zu entfernen und Speicherplatz zu sparen. Etwas wie das:
NSMutableSet *seen = [NSMutableSet set];
NSUInteger i = 0;
while (i < [originalArray count]) {
id obj = [originalArray objectAtIndex:i];
if ([seen containsObject:obj]) {
[originalArray removeObjectAtIndex:i];
// NB: we *don't* increment i here; since
// we've removed the object previously at
// index i, [originalArray objectAtIndex:i]
// now points to the next object in the array.
} else {
[seen addObject:obj];
i++;
}
}
UPDATE : Yuri Niyazov wies darauf hin, dass meine letzte Antwort tatsächlich in O (N 2 ) removeObjectAtIndex:läuft, weil sie wahrscheinlich in O (N) läuft.
(Er sagt "wahrscheinlich", weil wir nicht genau wissen, wie es implementiert ist. Eine mögliche Implementierung ist jedoch, dass die Methode nach dem Löschen des Objekts am Index X jedes Element vom Index X + 1 bis zum letzten Objekt im Array durchläuft Wenn dies der Fall ist, ist dies tatsächlich die O (N) -Leistung.)
Also, was tun? Es hängt von der Situation ab. Wenn Sie ein großes Array haben und nur eine kleine Anzahl von Duplikaten erwarten, funktioniert die direkte Deduplizierung einwandfrei und Sie müssen kein doppeltes Array erstellen. Wenn Sie ein Array haben, in dem Sie viele Duplikate erwarten, ist der Aufbau eines separaten, nicht duplizierten Arrays wahrscheinlich der beste Ansatz. Das Mitnehmen hier ist, dass die Big-O-Notation nur die Eigenschaften eines Algorithmus beschreibt und Ihnen nicht definitiv sagt, welche für einen bestimmten Umstand am besten ist.
Wenn Sie auf iOS 5+ abzielen (was die gesamte iOS-Welt abdeckt), verwenden Sie es am besten NSOrderedSet. Es entfernt Duplikate und behält die Reihenfolge Ihrer NSArray.
Mach einfach
NSOrderedSet *orderedSet = [NSOrderedSet orderedSetWithArray:yourArray];
Sie können es jetzt wieder in ein eindeutiges NSArray konvertieren
NSArray *uniqueArray = orderedSet.array;
Oder verwenden Sie einfach das orderSet, da es die gleichen Methoden wie ein NSArray objectAtIndex:hat firstObjectund so weiter.
Ein Mitgliedschafts-Check mit containsist auf dem noch schneller NSOrderedSetals auf einemNSArray
Weitere Informationen finden Sie in der NSOrderedSet-Referenz
Verfügbar in OS X 10.7 und höher.
Wenn Sie sich Sorgen um die Bestellung machen, ist dies der richtige Weg
NSArray *no = [[NSOrderedSet orderedSetWithArray:originalArray]allObjects];
Hier ist der Code zum Entfernen doppelter Werte aus NSArray in der Reihenfolge.
brauche Bestellung
NSArray *yourarray = @[@"a",@"b",@"c"];
NSOrderedSet *orderedSet = [NSOrderedSet orderedSetWithArray:yourarray];
NSArray *arrayWithoutDuplicates = [orderedSet array];
NSLog(@"%@",arrayWithoutDuplicates);
oder brauche keine Bestellung
NSSet *set = [NSSet setWithArray:yourarray];
NSArray *arrayWithoutOrder = [set allObjects];
NSLog(@"%@",arrayWithoutOrder);
Hier habe ich doppelte Namenswerte aus mainArray entfernt und das Ergebnis in NSMutableArray (listOfUsers) gespeichert.
for (int i=0; i<mainArray.count; i++) {
if (listOfUsers.count==0) {
[listOfUsers addObject:[mainArray objectAtIndex:i]];
}
else if ([[listOfUsers valueForKey:@"name" ] containsObject:[[mainArray objectAtIndex:i] valueForKey:@"name"]])
{
NSLog(@"Same object");
}
else
{
[listOfUsers addObject:[mainArray objectAtIndex:i]];
}
}
Beachten Sie, dass Sie bei einem sortierten Array nicht mit jedem anderen Element im Array vergleichen müssen, sondern nur mit dem letzten Element. Dies sollte viel schneller sein als die Überprüfung aller Elemente.
// sortedSourceArray is the source array, already sorted
NSMutableArray *newArray = [[NSMutableArray alloc] initWithObjects:[sortedSourceArray objectAtIndex:0]];
for (int i = 1; i < [sortedSourceArray count]; i++)
{
if (![[sortedSourceArray objectAtIndex:i] isEqualToString:[sortedSourceArray objectAtIndex:(i-1)]])
{
[newArray addObject:[tempArray objectAtIndex:i]];
}
}
Es sieht so aus, als ob die NSOrderedSetAntworten, die ebenfalls vorgeschlagen werden, viel weniger Code erfordern. Wenn Sie jedoch NSOrderedSetaus irgendeinem Grund keinen verwenden können und ein sortiertes Array haben, ist meine Lösung meiner Meinung nach die schnellste. Ich bin mir nicht sicher, wie es mit der Geschwindigkeit der NSOrderedSetLösungen verglichen wird. Beachten Sie auch, dass mein Code mit überprüft isEqualToString:, sodass dieselbe Buchstabenfolge nicht mehr als einmal in angezeigt wird newArray. Ich bin nicht sicher, ob die NSOrderedSetLösungen Duplikate basierend auf dem Wert oder basierend auf dem Speicherort entfernen.
In meinem Beispiel wird davon sortedSourceArrayausgegangen, dass nur NSStrings, nur NSMutableStrings oder eine Mischung aus beiden enthalten ist. Wenn sortedSourceArraystattdessen nur NSNumbers oder nur NSDates enthält, können Sie ersetzen
if (![[sortedSourceArray objectAtIndex:i] isEqualToString:[sortedSourceArray objectAtIndex:(i-1)]])
mit
if ([[sortedSourceArray objectAtIndex:i] compare:[sortedSourceArray objectAtIndex:(i-1)]] != NSOrderedSame)
und es sollte perfekt funktionieren. Wenn es sortedSourceArrayeine Mischung aus NSStrings, NSNumbers und / oder NSDates enthält, wird es wahrscheinlich abstürzen.
Es gibt einen KVC- Objektoperator , der eine elegantere Lösung bietet. uniquearray = [yourarray valueForKeyPath:@"@distinctUnionOfObjects.self"];Hier ist eine NSArray-Kategorie .
Eine weitere einfache Möglichkeit, die Sie ausprobieren können, um vor dem Hinzufügen eines Objekts zum Array keinen doppelten Wert hinzuzufügen: -
// Angenommen, mutableArray wird zugewiesen und initialisiert und enthält einen Wert
if (![yourMutableArray containsObject:someValue])
{
[yourMutableArray addObject:someValue];
}
Entfernen Sie doppelte Werte aus NSMutableArray in Objective-C
NSMutableArray *datelistArray = [[NSMutableArray alloc]init];
for (Student * data in fetchStudentDateArray)
{
if([datelistArray indexOfObject:data.date] == NSNotFound)
[datelistArray addObject:data.date];
}
Hier ist der Code zum Entfernen doppelter Werte aus dem NSMutable Array. .es wird für Sie arbeiten. myArray ist Ihr veränderbares Array, mit dem Sie doppelte Werte entfernen möchten.
for(int j = 0; j < [myMutableArray count]; j++){
for( k = j+1;k < [myMutableArray count];k++){
NSString *str1 = [myMutableArray objectAtIndex:j];
NSString *str2 = [myMutableArray objectAtIndex:k];
if([str1 isEqualToString:str2])
[myMutableArray removeObjectAtIndex:k];
}
} // Now print your array and will see there is no repeated value
Verwenden Sie einfach diesen einfachen Code:
NSArray *hasDuplicates = /* (...) */;
NSArray *noDuplicates = [[NSSet setWithArray: hasDuplicates] allObjects];
da nsset keine doppelten Werte zulässt und alle Objekte ein Array zurückgeben
NSOrderedSetinsteed von NSSet.