NSPredicateを使用してNSDictionaryキーに基づいてNSArrayをフィルタリングする


94

辞書がたくさんあります。

キーに基づいて配列をフィルター処理したいのですが。

私はこれを試しました:

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

NSArray *filteredArray = [data filteredArrayUsingPredicate:predicate];

これは機能しません。結果はありません。私は何か間違っていると思います。「SPORT」がivarであった場合、これがメソッドであることは知っています。それが鍵だとしたら、おそらく違うと思います。

しかし、私は例を見つけることができませんでした。

ありがとう


更新

検索している文字列を引用符で囲みました。

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

それでも動作しません。


アップデート2

解決しました。私は実際には一重引用符を削除する必要がありましたが、これはガイドの言うことに反するようです。

私の本当の問題は、ネストされた配列があり、実際に辞書を評価していなかったことです。骨頭が動く。


述語はデフォルトで大文字と小文字が区別されることを言及するだけです([c]を使用すると、区別されなくなります)。
groumpf 2010

回答:


151

データ変数が実際にキーSPORTのディクショナリを含む配列である限り、機能するはずです。

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

この場合、フィルターには辞書が含まれます。

(%@は引用符で囲む必要はありません。これは、NSPredicateがオブジェクトを作成するときに行われます。)


NSPredicateはiPhoneで動作しますか?これはシムでうまく機能しますが、iPhoneで実行すると、NSPredicateクラスが見つからないというエラーが発生します。
lostInTransit 2009

NSPredicateはiOS 3.0以降で使用できます。
ゼケル

1
私のような新しいコーダーを明確にするために、コードの重要な行は 'NSArray * filtered = [data FilteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@ "(BAR ==%@)"、@ "foo"]];'です。ここで、 'data'は、すでにコードに含まれているnsdictionariesのnsarrayです。(スラケンありがとう)
TMR、2015年

キー名が動的な場合はどうなりますか?
iPeter 2017

27

私はそれが古いニュースであることを知っていますが、私の2セントを追加します。デフォルトLIKE[cd]では、だけではなくコマンドを使用します[c][d]アクセント記号付きの文字を比較します。これは、私のWarcraftアプリで特にうまく機能します。ユーザーが「Vòódòó」と名前を入力すると、テーブルビューで名前を検索することがほぼ不可能になります。[d]述語の間に彼らのアクセント記号を取り除きます。したがって、Vòódòóという名前を含むオブジェクトを返す@"name LIKE[CD] %@", object.namewhereの述語object.name == @"voodoo"

Appleのドキュメントから:like [cd]は「大文字と小文字を区別しないlike」を意味します。)文字列構文の完全な説明と使用可能なすべての演算子のリストについては、述語フォーマット文字列構文を参照してください。


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 iPhone 3.0でのみ利用できます。

デバイスで実行しようとするまで、そのことに気付かないでしょう。


0

Swift 3では、辞書のキーと値に基づいて述語で辞書の配列をフィルタリングする場合、次のパターンのいずれかを選択できます。


#1。NSPredicate init(format:arguments:)初期化子を使用する

Objective-Cの場合init(format:arguments:)は、述語を評価するためのKey-Valueコーディングスタイルを提供します。

使用法:

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:)初期化子を使用する

ご希望の場合は別の方法として、強く型付けされた以上のAPI stringly入力された APIを、あなたが使用することができますinit(block:)初期化子。

使用法:

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リファレンスを見ると、置換文字を引用符で囲む必要があるようです。たとえば、現在の述語は次のようになります。(SPORT == Football)読み取りたい(SPORT == 'Football')ので、フォーマット文字列はである必要があります@"(SPORT == '%@')"


それもそうだと思いました。どうやら引用符は必要ありません。ガイドが引用すべき言葉を「すべき」と正確に言っているのか、私には正確にはわかりません。
コーリーフロイド
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.