Sử dụng NSPredicate để lọc một NSArray dựa trên các khóa NSDictionary


94

Tôi có một loạt các từ điển.

Tôi muốn lọc mảng dựa trên một khóa.

Tôi đã thử điều này:

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

NSArray *filteredArray = [data filteredArrayUsingPredicate:predicate];

Điều này không hiệu quả, tôi không nhận được kết quả. Tôi nghĩ tôi đang làm gì đó sai. Tôi biết đây là phương pháp nếu "SPORT" là một ivar. Tôi nghĩ nó có lẽ là khác nếu nó là một chìa khóa.

Tuy nhiên, tôi đã không thể tìm thấy một ví dụ.

Cảm ơn


Cập nhật

Tôi đã thêm dấu ngoặc kép xung quanh chuỗi mà tôi đang tìm kiếm.

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

Nó vẫn không hoạt động.


Cập nhật 2

Đã giải quyết nó. Tôi thực sự đã phải loại bỏ các dấu ngoặc kép đơn lẻ, có vẻ như đi ngược lại với những gì hướng dẫn nói.

Vấn đề thực sự của tôi là tôi có một mảng lồng nhau và tôi không thực sự đánh giá các từ điển. Đầu xương chuyển động.


Chỉ cần đề cập rằng vị từ phân biệt chữ hoa chữ thường theo mặc định (sử dụng [c] để không phân biệt).
ngổ ngáo

Câu trả lời:


151

Nó sẽ hoạt động - miễn là biến dữ liệu thực sự là một mảng chứa từ điển với khóa SPORT

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

Lọc trong trường hợp này có chứa từ điển.

(% @ không cần phải được trích dẫn, điều này được thực hiện khi NSPredicate tạo đối tượng.)


NSPredicate có hoạt động trên iPhone không? Nó hoạt động tốt trên sim nhưng chạy nó trên iPhone thì lại xuất hiện lỗi không thể tìm thấy lớp NSPredicate.
lostInTransit

NSPredicate có sẵn kể từ iOS 3.0.
zekel

1
để làm rõ đối với những lập trình viên mới như tôi, dòng mã chính là 'NSArray * filter = [data filterArrayUsingPredicate: [NSPredicate predicateWithFormat: @ "(BAR ==% @)", @ "foo"]];' trong đó 'data' là nsarray của nsdictionaries đã có trong mã của bạn. (cảm ơn bạn suraken)
tmr

Điều gì sẽ xảy ra nếu các tên khóa là động?
iPeter

27

Tôi biết đó là tin cũ nhưng để thêm hai xu của tôi. Theo mặc định, tôi sử dụng các lệnh LIKE[cd]thay vì chỉ [c]. Các [d]so sánh chữ với các biểu tượng giọng. Điều này đặc biệt hiệu quả trong Ứng dụng Warcraft của tôi, nơi mọi người đánh vần tên của họ là "Vòódòó" khiến việc tìm kiếm tên của họ trong chế độ xem bảng gần như không thể. Các [d]dải ký hiệu trọng âm của chúng trong vị ngữ. Vì vậy, một vị từ của @"name LIKE[CD] %@", object.namenơi object.name == @"voodoo"sẽ trả về đối tượng chứa tên Vòódòó.

Từ tài liệu của Apple: như [cd] có nghĩa là “giống như chữ hoa chữ thường và dấu phụ-không phân biệt.”) Để biết mô tả đầy đủ về cú pháp chuỗi và danh sách tất cả các toán tử có sẵn, hãy xem Định dạng dự đoán Cú pháp chuỗi .


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 chỉ có sẵn trong iPhone 3.0.

Bạn sẽ không nhận thấy điều đó cho đến khi thử chạy trên thiết bị.


0

Với Swift 3, khi bạn muốn lọc một mảng từ điển với một vị từ dựa trên các khóa và giá trị từ điển, bạn có thể chọn một trong các mẫu sau.


# 1. Sử dụng trình NSPredicate init(format:arguments:)khởi tạo

Nếu bạn đến từ Objective-C, hãy init(format:arguments:)cung cấp kiểu mã hóa khóa-giá trị để đánh giá vị từ của bạn.

Sử dụng:

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. Sử dụng trình NSPredicate init(block:)khởi tạo

Để thay thế nếu bạn thích các API được gõ mạnh hơn các API được gõ theo chuỗi , bạn có thể sử dụng trình init(block:)khởi tạo.

Sử dụng:

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

Nhìn vào tham chiếu NSPredicate , có vẻ như bạn cần đặt ký tự thay thế của mình bằng dấu ngoặc kép. Ví dụ: vị từ hiện tại của bạn đọc: (SPORT == Football)Bạn muốn nó đọc (SPORT == 'Football'), vì vậy chuỗi định dạng của bạn cần phải như vậy @"(SPORT == '%@')".


Tôi cũng nghĩ đó là những gì nó nói. Rõ ràng là các trích dẫn không cần thiết. Tôi không chắc chính xác hướng dẫn đang nói dấu ngoặc kép "nên" được sử dụng để làm gì.
Corey Floyd
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.