NSArray'ı NSDictionary anahtarlarına göre filtrelemek için NSPredicate kullanma


94

Bir dizi sözlüğüm var.

Diziyi bir anahtara göre filtrelemek istiyorum.

Bunu denedim:

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

NSArray *filteredArray = [data filteredArrayUsingPredicate:predicate];

Bu işe yaramıyor, sonuç alamıyorum. Sanırım yanlış bir şey yapıyorum. "SPORT" bir ivar olsaydı bu yöntem olduğunu biliyorum. Bir anahtar ise muhtemelen farklı olduğunu düşünüyorum.

Ancak bir örnek bulamadım.

Teşekkürler


Güncelleme

Aradığım dizenin etrafına tırnak işaretleri ekledim.

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

Hala çalışmıyor.


Güncelleme 2

Çözüldü. Aslında, kılavuzun söylediklerine aykırı görünen tek alıntıları kaldırmak zorunda kaldım.

Asıl sorunum, iç içe geçmiş bir dizim vardı ve sözlükleri gerçekten değerlendirmiyordum. Kemik kafa hareketi.


Sadece yüklemin varsayılan olarak büyük / küçük harfe duyarlı olduğunu belirtmek isterim (duyarlı olmamak için [c] kullanın).
groumpf

Yanıtlar:


151

Çalışmalıdır - veri değişkeni aslında SPORT anahtarına sahip bir sözlük içeren bir dizi olduğu sürece

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

Bu durumda filtrelenmiş sözlüğü içerir.

(% @ 'nin alıntılanması gerekmez, bu, NSPredicate nesneyi oluşturduğunda yapılır.)


NSPredicate iPhone'da çalışıyor mu? Sim üzerinde harika çalışıyor ancak iPhone'da çalıştırmak, NSPredicate sınıfının bulunamaması gibi bir hata veriyor.
lostInTransit

NSPredicate, iOS 3.0'dan beri mevcuttur.
zekel

1
benim gibi yeni kodlayıcıları açıklığa kavuşturmak için, kodun anahtar satırı 'NSArray * filtered = [data filteredArrayUsingPredicate: [NSPredicate tahminWithFormat: @ "(BAR ==% @)", @ "foo"]];' Burada 'veri', kodunuzda zaten bulunan nsdictionaries dizisidir. (teşekkür ederim)
tmr

Ya anahtar isimler dinamikse?
iPeter

27

Bunun eski bir haber olduğunu biliyorum ama iki sentimi de eklemek gerekir. Varsayılan olarak komutları LIKE[cd]sadece kullanmak yerine kullanıyorum [c]. [d]Aksan sembollerle harfleri karşılaştırır. Bu, özellikle insanların adlarını "Vòódòó" yazarak bir tablo görünümünde adlarını aramayı neredeyse imkansız hale getirdiği Warcraft Uygulamamda işe yarar. [d]Yüklem sırasında vurgu sembollerini şeritler. Dolayısıyla , Vòódòó adını içeren nesneyi @"name LIKE[CD] %@", object.namenereye object.name == @"voodoo"döndüreceğinin bir koşulu.

Apple belgelerinden: [cd] gibi "büyük / küçük harf ve aksan-duyarsız" anlamına gelir.) Dize sözdiziminin tam bir açıklaması ve mevcut tüm operatörlerin listesi için bkz . Biçim Dizesi Sözdizimini Tahmin Et .


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 yalnızca iPhone 3.0'da mevcuttur.

Cihazda çalıştırmayı deneyene kadar bunu fark etmeyeceksiniz.


0

Swift 3 ile, sözlük anahtarlarına ve değerlerine dayalı bir yüklemle bir dizi sözlüğü filtrelemek istediğinizde, aşağıdaki kalıplardan birini seçebilirsiniz.


# 1. NSPredicate init(format:arguments:)Başlatıcı kullanma

Objective-C'den geliyorsanız init(format:arguments:), yükleminizi değerlendirmek için bir anahtar-değer kodlama stili sunar.

Kullanım:

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. NSPredicate init(block:)Başlatıcı kullanma

Alternatif olarak , dizgi şeklinde yazılmış API'ler yerine güçlü yazılmış API'leri tercih ediyorsanız, başlatıcıyı kullanabilirsiniz .init(block:)

Kullanım:

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

NSPredicate referansına bakıldığında, ikame karakterinizi tırnak içine almanız gerekiyor gibi görünüyor. Örneğin, şu anki yükleminiz okur: Okumasını (SPORT == Football)istiyorsunuz (SPORT == 'Football'), bu yüzden biçim dizenizin olması gerekir @"(SPORT == '%@')".


Ben de öyle söylediğini düşündüm. Görünüşe göre alıntılara gerek yok. Rehberin alıntıların "ne için kullanılması gerektiğini" söylediğinden tam olarak emin değilim.
Corey Floyd
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.