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.