Verwenden von NSPredicate zum Filtern eines NSArray basierend auf NSDictionary-Schlüsseln

94

Ich habe eine Reihe von Wörterbüchern.

Ich möchte das Array basierend auf einem Schlüssel filtern.

Ich habe es versucht:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(SPORT ==  %@)", @"Football"];

NSArray *filteredArray = [data filteredArrayUsingPredicate:predicate];

Das funktioniert nicht, ich bekomme keine Ergebnisse. Ich glaube, ich mache etwas falsch. Ich weiß, dass dies die Methode ist, wenn "SPORT" ein Ivar war. Ich denke, es ist wahrscheinlich anders, wenn es ein Schlüssel ist.

Ich konnte jedoch kein Beispiel finden.

Vielen Dank


Aktualisieren

Ich habe die gesuchte Zeichenfolge in Anführungszeichen gesetzt.

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(SPORT ==  '%@')", @"Football"];

Es funktioniert immer noch nicht.


Update 2

Ich habe es gelöst. Ich musste tatsächlich die einfachen Anführungszeichen entfernen, was gegen das zu verstoßen scheint, was der Leitfaden sagt.

Mein eigentliches Problem ist, dass ich ein verschachteltes Array hatte und die Wörterbücher nicht ausgewertet habe. Knochenkopf bewegen.

Corey Floyd
quelle
Nur um zu erwähnen, dass das Prädikat standardmäßig zwischen Groß- und Kleinschreibung unterscheidet (verwenden Sie [c], um die Groß- und Kleinschreibung zu unterscheiden).
Groumpf

Antworten:

151

Es sollte funktionieren - solange die Datenvariable tatsächlich ein Array ist, das ein Wörterbuch mit dem Schlüssel SPORT enthält

NSArray *data = [NSArray arrayWithObject:[NSMutableDictionary dictionaryWithObject:@"foo" forKey:@"BAR"]];    
NSArray *filtered = [data filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"(BAR == %@)", @"foo"]];

Gefiltert in diesem Fall enthält das Wörterbuch.

(% @ muss nicht in Anführungszeichen gesetzt werden. Dies erfolgt, wenn NSPredicate das Objekt erstellt.)

erwacht
quelle
Funktioniert NSPredicate auf dem iPhone? Es funktioniert hervorragend auf der Sim, aber wenn es auf dem iPhone ausgeführt wird, tritt der Fehler auf, dass die NSPredicate-Klasse nicht gefunden wurde.
lostInTransit
NSPredicate ist seit iOS 3.0 verfügbar.
Zekel
1
Um dies für neue Codierer wie mich zu verdeutlichen, lautet die Schlüsselzeile des Codes 'NSArray * filtered = [data filteredArrayUsingPredicate: [NSPredicate predicateWithFormat: @ "(BAR ==% @)", @ "foo"]];' Dabei ist 'data' das nsarray von nsdictionaries, das sich bereits in Ihrem Code befindet. (danke erwacht)
tmr
Was ist, wenn die Schlüsselnamen dynamisch sind?
iPeter
27

Ich weiß, es sind alte Nachrichten, aber um meine zwei Cent hinzuzufügen. Standardmäßig verwende ich die Befehle LIKE[cd]und nicht nur [c]. Der [d]vergleicht Buchstaben mit Akzentsymbolen. Dies funktioniert besonders gut in meiner Warcraft-App, in der Benutzer ihren Namen "Vòódòó" buchstabieren, sodass es fast unmöglich ist, in einer Tabellenansicht nach ihrem Namen zu suchen. Die [d]Streifen ihre Akzentsymbole während des Prädikats. Ein Prädikat von @"name LIKE[CD] %@", object.namewhere object.name == @"voodoo"gibt also das Objekt mit dem Namen Vòódòó zurück.

Aus der Apple-Dokumentation: like [cd] bedeutet "case- und diakritisch-unempfindlich like". Eine vollständige Beschreibung der String-Syntax und eine Liste aller verfügbaren Operatoren finden Sie unter Predicate Format String Syntax .

ChargedNeuron
quelle
11
#import <Foundation/Foundation.h>
// clang -framework Foundation Siegfried.m 
    int
main() {
    NSArray *arr = @[
        @{@"1" : @"Fafner"},
        @{@"1" : @"Fasolt"}
    ];
    NSPredicate *p = [NSPredicate predicateWithFormat:
        @"SELF['1'] CONTAINS 'e'"];
    NSArray *res = [arr filteredArrayUsingPredicate:p];
    NSLog(@"Siegfried %@", res);
    return 0;
}
Isaak Osipovich Dunayevsky
quelle
3

NSPredicate ist nur in iPhone 3.0 verfügbar.

Sie werden das erst bemerken, wenn Sie versuchen, es auf dem Gerät auszuführen.

Stange
quelle
0

Wenn Sie mit Swift 3 ein Array von Wörterbüchern mit einem Prädikat filtern möchten, das auf Wörterbuchschlüsseln und -werten basiert, können Sie eines der folgenden Muster auswählen.


# 1. Mit NSPredicate init(format:arguments:)initializer

Wenn Sie aus Objective-C stammen, init(format:arguments:)bietet es einen Schlüsselwert-Codierungsstil zur Bewertung Ihres Prädikats.

Verwendung:

import Foundation

let array = [["key1": "value1", "key2": "value2"], ["key1": "value3"], ["key3": "value4"]]

let predicate = NSPredicate(format: "key1 == %@", "value1")
//let predicate = NSPredicate(format: "self['key1'] == %@", "value1") // also works
let filteredArray = array.filter(predicate.evaluate)

print(filteredArray) // prints: [["key2": "value2", "key1": "value1"]]

# 2. Mit NSPredicate init(block:)initializer

Alternativ können Sie den Initialisierer verwenden, wenn Sie stark typisierte APIs gegenüber streng typisierten APIs bevorzugen init(block:).

Verwendung:

import Foundation

let array = [["key1": "value1", "key2": "value2"], ["key1": "value3"], ["key3": "value4"]]

let dictPredicate = NSPredicate(block: { (obj, _) in
    guard let dict = obj as? [String: String], let value = dict["key1"] else { return false }
    return value == "value1"
})

let filteredArray = array.filter(dictPredicate.evaluate)
print(filteredArray) // prints: [["key2": "value2", "key1": "value1"]]
Imanou Petit
quelle
-1

Wenn Sie sich die NSPredicate-Referenz ansehen , müssen Sie Ihr Ersetzungszeichen mit Anführungszeichen umgeben. Beispiel: Ihr aktuelles Prädikat lautet: (SPORT == Football)Sie möchten, dass es gelesen wird (SPORT == 'Football'), daher muss Ihre Formatzeichenfolge sein @"(SPORT == '%@')".

Martin Gordon
quelle
Ich dachte, das hat es auch gesagt. Anscheinend werden die Zitate nicht benötigt. Ich bin mir nicht sicher, wofür der Leitfaden sagt, dass Anführungszeichen verwendet werden sollten.
Corey Floyd