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

답변:


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

NSPredicate는 iOS 3.0부터 사용할 수 있습니다.
— zekel 2012

1
저와 같은 새로운 코더를 명확히하기 위해 코드의 핵심 라인은 'NSArray * filtered = [data filtersArrayUsingPredicate : [NSPredicate predicateWithFormat : @ "(BAR == % @)", @ "foo"]];'입니다. 여기서 'data'는 이미 코드에있는 nsdictionaries의 nsarray입니다. (수라 켄 감사합니다)
— tmr

키 이름이 동적이면 어떻게됩니까?
— iPeter

27

나는 그것이 오래된 뉴스라는 것을 알고 있지만 2 센트를 더합니다. 기본적으로 나는 명령을 사용하여 LIKE[cd]단지보다는 [c]. 는 [d]악센트 기호 문자를 비교합니다. 이 기능은 사람들이 "Vòódòó"라는 이름의 철자를 쓰는 워크래프트 앱에서 특히 잘 작동하여 테이블 뷰에서 이름을 검색하는 것이 거의 불가능합니다. 는 [d]술어 동안 자신의 악센트 기호를 제거합니다. 따라서 @"name LIKE[CD] %@", object.name어디에 대한 술어는 object.name == @"voodoo"Vòódòó라는 이름을 포함하는 객체를 반환합니다.

Apple 문서에서 : like [cd]는 "대소 문자 구분 기호를 구분하지 않는 like"를 의미합니다.) 문자열 구문에 대한 전체 설명과 사용 가능한 모든 연산자 목록은 Predicate Format String Syntax를 참조하십시오 .


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:)술어를 평가하기위한 키-값 코딩 스타일을 제공합니다.

용법:

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 보다 강력한 형식의 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)You want it to read (SPORT == 'Football'), 따라서 형식 문자열은 @"(SPORT == '%@')".


저도 그렇게 말한 줄 알았어요. 분명히 따옴표가 필요하지 않습니다. 가이드가 따옴표를 "사용해야한다"고 말하는 것이 정확히 무엇인지 모르겠습니다.
— Corey Floyd
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.