Ich habe ein NSDictionary (in einer Liste gespeichert), das ich grundsätzlich als assoziatives Array verwende (Zeichenfolgen als Schlüssel und Werte). Ich möchte das Array von Schlüsseln als Teil meiner Anwendung verwenden, möchte jedoch, dass sie in einer bestimmten Reihenfolge vorliegen (nicht wirklich in einer Reihenfolge, in der ich einen Algorithmus zum Sortieren schreiben kann). Ich könnte immer ein separates Array der Schlüssel speichern, aber das scheint irgendwie kludgey, weil ich immer die Schlüssel des Wörterbuchs sowie die Werte des Arrays aktualisieren und sicherstellen müsste, dass sie immer übereinstimmen. Momentan verwende ich nur [myDictionary allKeys], aber dies gibt sie offensichtlich in einer beliebigen, nicht garantierten Reihenfolge zurück. Gibt es eine Datenstruktur in Objective-C, die mir fehlt? Hat jemand Vorschläge, wie man das eleganter macht?
quelle
Ich bin zu spät zum Spiel mit einer tatsächlichen Antwort, aber Sie könnten interessiert sein, CHOrderedDictionary zu untersuchen . Es ist eine Unterklasse von NSMutableDictionary, die eine andere Struktur zur Aufrechterhaltung der Schlüsselreihenfolge kapselt. (Es ist Teil von CHDataStructures.framework .) Ich finde es bequemer, als ein Wörterbuch und ein Array getrennt zu verwalten.
Offenlegung: Dies ist Open-Source-Code, den ich geschrieben habe. Ich hoffe nur, dass es für andere nützlich sein kann, die mit diesem Problem konfrontiert sind.
quelle
Es gibt keine solche eingebaute Methode, mit der Sie diese erwerben können. Aber eine einfache Logik funktioniert für Sie. Sie können einfach einige numerische Texte vor jede Taste einfügen, während Sie das Wörterbuch vorbereiten. Mögen
NSDictionary *dict = [[NSDictionary alloc] initWithObjectsAndKeys: @"01.Created",@"cre", @"02.Being Assigned",@"bea", @"03.Rejected",@"rej", @"04.Assigned",@"ass", @"05.Scheduled",@"sch", @"06.En Route",@"inr", @"07.On Job Site",@"ojs", @"08.In Progress",@"inp", @"09.On Hold",@"onh", @"10.Completed",@"com", @"11.Closed",@"clo", @"12.Cancelled", @"can", nil];
Wenn Sie jetzt sortingArrayUsingSelector verwenden können, während Sie alle Schlüssel in derselben Reihenfolge abrufen, in der Sie sie platziert haben.
NSArray *arr = [[dict allKeys] sortedArrayUsingSelector:@selector(localizedStandardCompare:)];
An der Stelle, an der Sie Tasten in UIView anzeigen möchten, hacken Sie einfach die vorderen 3 Zeichen ab.
quelle
Wenn Sie NSDictionary in Unterklassen unterteilen möchten, müssen Sie mindestens folgende Methoden implementieren:
-count
-objectForKey:
-keyEnumerator
-removeObjectForKey:
-setObject:forKey:
-copyWithZone:
-mutableCopyWithZone:
-encodeWithCoder:
-initWithCoder:
-countByEnumeratingWithState:objects:count:
Der einfachste Weg, das zu tun, was Sie wollen, besteht darin, eine Unterklasse von NSMutableDictionary zu erstellen, die ein eigenes NSMutableDictionary enthält, das manipuliert wird, und ein NSMutableArray, um einen geordneten Satz von Schlüsseln zu speichern.
Wenn Sie Ihre Objekte niemals codieren möchten, können Sie die Implementierung
-encodeWithCoder:
und überspringen-initWithCoder:
Alle Ihre Methodenimplementierungen in den 10 oben genannten Methoden würden dann entweder direkt durch Ihr gehostetes Wörterbuch oder Ihr geordnetes Schlüsselarray gehen.
quelle
Mein kleiner Zusatz: Sortieren nach Zifferntasten (Verwenden von Kurzschreibweisen für kleineren Code)
// the resorted result array NSMutableArray *result = [NSMutableArray new]; // the source dictionary - keys may be Ux timestamps (as integer, wrapped in NSNumber) NSDictionary *dict = @{ @0: @"a", @3: @"d", @1: @"b", @2: @"c" }; {// do the sorting to result NSArray *arr = [[dict allKeys] sortedArrayUsingSelector:@selector(compare:)]; for (NSNumber *n in arr) [result addObject:dict[n]]; }
quelle
Schnell und schmutzig:
Wenn Sie Ihr Wörterbuch bestellen müssen (hier als "myDict" bezeichnet), gehen Sie folgendermaßen vor:
NSArray *ordering = [NSArray arrayWithObjects: @"Thing",@"OtherThing",@"Last Thing",nil];
Wenn Sie dann Ihr Wörterbuch bestellen müssen, erstellen Sie einen Index:
NSEnumerator *sectEnum = [ordering objectEnumerator]; NSMutableArray *index = [[NSMutableArray alloc] init]; id sKey; while((sKey = [sectEnum nextObject])) { if ([myDict objectForKey:sKey] != nil ) { [index addObject:sKey]; } }
Jetzt enthält das Indexindexobjekt * die entsprechenden Schlüssel in der richtigen Reihenfolge. Beachten Sie, dass für diese Lösung nicht unbedingt alle Schlüssel vorhanden sein müssen. Dies ist die übliche Situation, mit der wir es zu tun haben ...
quelle
Für Swift 3 . Bitte probieren Sie den folgenden Ansatz aus
//Sample Dictionary let dict: [String: String] = ["01.One": "One", "02.Two": "Two", "03.Three": "Three", "04.Four": "Four", "05.Five": "Five", "06.Six": "Six", "07.Seven": "Seven", "08.Eight": "Eight", "09.Nine": "Nine", "10.Ten": "Ten" ] //Print the all keys of dictionary print(dict.keys) //Sort the dictionary keys array in ascending order let sortedKeys = dict.keys.sorted { $0.localizedCaseInsensitiveCompare($1) == ComparisonResult.orderedAscending } //Print the ordered dictionary keys print(sortedKeys) //Get the first ordered key var firstSortedKeyOfDictionary = sortedKeys[0] // Get range of all characters past the first 3. let c = firstSortedKeyOfDictionary.characters let range = c.index(c.startIndex, offsetBy: 3)..<c.endIndex // Get the dictionary key by removing first 3 chars let firstKey = firstSortedKeyOfDictionary[range] //Print the first key print(firstKey)
quelle
Minimale Implementierung einer geordneten Unterklasse von NSDictionary (basierend auf https://github.com/nicklockwood/OrderedDictionary ). Fühlen Sie sich frei, für Ihre Bedürfnisse zu erweitern:
Swift 3 und 4
class MutableOrderedDictionary: NSDictionary { let _values: NSMutableArray = [] let _keys: NSMutableOrderedSet = [] override var count: Int { return _keys.count } override func keyEnumerator() -> NSEnumerator { return _keys.objectEnumerator() } override func object(forKey aKey: Any) -> Any? { let index = _keys.index(of: aKey) if index != NSNotFound { return _values[index] } return nil } func setObject(_ anObject: Any, forKey aKey: String) { let index = _keys.index(of: aKey) if index != NSNotFound { _values[index] = anObject } else { _keys.add(aKey) _values.add(anObject) } } }
Verwendung
let normalDic = ["hello": "world", "foo": "bar"] // initializing empty ordered dictionary let orderedDic = MutableOrderedDictionary() // copying normalDic in orderedDic after a sort normalDic.sorted { $0.0.compare($1.0) == .orderedAscending } .forEach { orderedDic.setObject($0.value, forKey: $0.key) } // from now, looping on orderedDic will be done in the alphabetical order of the keys orderedDic.forEach { print($0) }
Ziel c
@interface MutableOrderedDictionary<__covariant KeyType, __covariant ObjectType> : NSDictionary<KeyType, ObjectType> @end @implementation MutableOrderedDictionary { @protected NSMutableArray *_values; NSMutableOrderedSet *_keys; } - (instancetype)init { if ((self = [super init])) { _values = NSMutableArray.new; _keys = NSMutableOrderedSet.new; } return self; } - (NSUInteger)count { return _keys.count; } - (NSEnumerator *)keyEnumerator { return _keys.objectEnumerator; } - (id)objectForKey:(id)key { NSUInteger index = [_keys indexOfObject:key]; if (index != NSNotFound) { return _values[index]; } return nil; } - (void)setObject:(id)object forKey:(id)key { NSUInteger index = [_keys indexOfObject:key]; if (index != NSNotFound) { _values[index] = object; } else { [_keys addObject:key]; [_values addObject:object]; } } @end
Verwendung
NSDictionary *normalDic = @{@"hello": @"world", @"foo": @"bar"}; // initializing empty ordered dictionary MutableOrderedDictionary *orderedDic = MutableOrderedDictionary.new; // copying normalDic in orderedDic after a sort for (id key in [normalDic.allKeys sortedArrayUsingSelector:@selector(compare:)]) { [orderedDic setObject:normalDic[key] forKey:key]; } // from now, looping on orderedDic will be done in the alphabetical order of the keys for (id key in orderedDic) { NSLog(@"%@:%@", key, orderedDic[key]); }
quelle
Ich mag C ++ nicht sehr, aber eine Lösung, die ich immer häufiger benutze, ist die Verwendung von Objective-C ++ und
std::map
aus der Standardvorlagenbibliothek. Es ist ein Wörterbuch, dessen Schlüssel beim Einfügen automatisch sortiert werden. Es funktioniert überraschend gut mit Skalartypen oder Objective-C-Objekten sowohl als Schlüssel als auch als Werte.Wenn Sie ein Array als Wert einfügen müssen, verwenden Sie einfach
std::vector
anstelle vonNSArray
.Eine Einschränkung ist, dass Sie möglicherweise Ihre eigene
insert_or_assign
Funktion bereitstellen möchten , es sei denn, Sie können C ++ 17 verwenden (siehe diese Antwort ). Außerdem müssen Sietypedef
Ihre Typen eingeben, um bestimmte Buildfehler zu vermeiden. Sobald Sie herausgefunden haben, wie man es benutztstd::map
, Iteratoren usw., ist es ziemlich einfach und schnell.quelle