Menggunakan NSPredicate untuk memfilter NSArray berdasarkan NSDictionary key


94

Saya memiliki banyak kamus.

Saya ingin memfilter array berdasarkan kunci.

Saya mencoba ini:

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

NSArray *filteredArray = [data filteredArrayUsingPredicate:predicate];

Ini tidak berhasil, saya tidak mendapatkan hasil. Saya pikir saya melakukan sesuatu yang salah. Saya tahu ini adalah metode jika "OLAHRAGA" adalah ivar. Saya pikir itu mungkin berbeda jika itu adalah kunci.

Namun saya belum dapat menemukan contoh.

Terima kasih


Memperbarui

Saya menambahkan tanda kutip di sekitar string yang saya cari.

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

Masih tidak bekerja.


Perbarui 2

Pecahkan itu. Saya sebenarnya harus menghapus tanda kutip tunggal, yang tampaknya bertentangan dengan apa yang dikatakan panduan.

Masalah sebenarnya saya adalah saya memiliki array bersarang dan saya tidak benar-benar mengevaluasi kamus. Gerakan kepala tulang.


Hanya untuk menyebutkan bahwa predikat bersifat case sensitive secara default (gunakan [c] untuk menjadi tidak sensitif).
groumpf

Jawaban:


151

Ini harus berfungsi - selama variabel data sebenarnya adalah array yang berisi kamus dengan kunci SPORT

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

Difilter dalam hal ini berisi kamus.

(% @ tidak harus dikutip, ini dilakukan saat NSPredicate membuat objek.)


Apakah NSPredicate berfungsi di iPhone? Ini berfungsi dengan baik pada sim tetapi menjalankannya di iPhone memberikan kesalahan bahwa kelas NSPredicate tidak dapat ditemukan.
lostInTransit

NSPredicate tersedia sejak iOS 3.0.
zekel

1
untuk memperjelas pembuat kode baru seperti saya, baris kuncinya adalah 'NSArray * filtered = [data filteredArrayUsingPredicate: [NSPredicate predicateWithFormat: @ "(BAR ==% @)", @ "foo"]];' di mana 'data' adalah larik nsdictionaries yang sudah ada di kode Anda. (terima kasih yakin)
tmr

Bagaimana jika nama kuncinya dinamis?
iPeter

27

Saya tahu itu berita lama tetapi menambahkan dua sen saya. Secara default saya menggunakan perintah LIKE[cd]daripada hanya [c]. The [d]membandingkan huruf dengan simbol aksen. Ini bekerja sangat baik di Aplikasi Warcraft saya di mana orang mengeja nama mereka "Vòódòó" sehingga hampir tidak mungkin untuk mencari nama mereka dalam tampilan tabel. The [d]strip simbol aksen mereka selama predikat. Jadi sebuah predikat @"name LIKE[CD] %@", object.namedimana object.name == @"voodoo"akan mengembalikan objek yang mengandung nama Vòódòó.

Dari dokumentasi Apple: like [cd] berarti “case- and diacritic-insensitive like”.) Untuk penjelasan lengkap tentang sintaks string dan daftar semua operator yang tersedia, lihat Format Predikat Sintaksis String .


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;
}

3

NSPredicate hanya tersedia di iPhone 3.0.

Anda tidak akan menyadarinya sampai mencoba menjalankan di perangkat.


0

Dengan Swift 3, saat Anda ingin memfilter array kamus dengan predikat berdasarkan kunci dan nilai kamus, Anda dapat memilih salah satu pola berikut.


# 1. Menggunakan NSPredicate init(format:arguments:)penginisialisasi

Jika Anda berasal dari Objective-C, init(format:arguments:)menawarkan gaya pengkodean nilai kunci untuk mengevaluasi predikat Anda.

Pemakaian:

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. Menggunakan NSPredicate init(block:)penginisialisasi

Sebagai alternatif jika Anda lebih suka API yang diketik dengan kuat daripada API yang diketik dengan string , Anda dapat menggunakan init(block:)penginisialisasi.

Pemakaian:

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"]]

-1

Melihat referensi NSPredicate , sepertinya Anda perlu mengelilingi karakter substitusi Anda dengan tanda kutip. Misalnya, predikat Anda saat ini berbunyi: (SPORT == Football)Anda ingin membaca (SPORT == 'Football'), jadi format string Anda harus @"(SPORT == '%@')".


Saya pikir itu juga yang dikatakannya. Rupanya tanda kutip tidak diperlukan. Saya tidak yakin persis apa kata panduan yang mengatakan bahwa kutipan "harus" digunakan.
Corey Floyd
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.