การใช้ NSPredicate เพื่อกรอง NSArray ตามคีย์ NSDictionary


94

ฉันมีพจนานุกรมมากมาย

ฉันต้องการกรองอาร์เรย์ตามคีย์

ฉันลองสิ่งนี้:

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

NSArray *filteredArray = [data filteredArrayUsingPredicate:predicate];

ไม่ได้ผลฉันไม่ได้รับผลลัพธ์ ฉันคิดว่าฉันทำอะไรผิด ฉันรู้ว่านี่เป็นวิธีการถ้า "SPORT" เป็นไอวาร์ ฉันคิดว่ามันอาจจะแตกต่างกันถ้าเป็นกุญแจ

อย่างไรก็ตามฉันไม่สามารถหาตัวอย่างได้

ขอบคุณ


อัปเดต

ฉันเพิ่มเครื่องหมายคำพูดรอบ ๆ สตริงที่ฉันกำลังค้นหา

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

1
เพื่อชี้แจงสำหรับผู้เขียนโค้ดรายใหม่เช่นฉันบรรทัดสำคัญของโค้ดคือ 'NSArray * filtered = [data filteredArrayUsingPredicate: [NSPredicate predicateWithFormat: @ "(BAR ==% @)", @ "foo"]]; โดยที่ 'data' คือ nsarray ของ nsdictionaries ที่มีอยู่แล้วในโค้ดของคุณ (ขอบคุณ suraken)
tmr

จะเกิดอะไรขึ้นถ้าชื่อคีย์เป็นแบบไดนามิก
iPeter

27

ฉันรู้ว่ามันเป็นข่าวเก่า แต่ต้องเพิ่มสองเซ็นต์ของฉัน โดยค่าเริ่มต้นฉันใช้คำสั่งLIKE[cd]มากกว่าแค่[c]. [d]เปรียบเทียบตัวอักษรที่มีสัญลักษณ์สำเนียง สิ่งนี้ใช้ได้ดีเป็นพิเศษในแอป Warcraft ของฉันที่ผู้คนสะกดชื่อ "Vòódòó" ทำให้แทบจะเป็นไปไม่ได้ที่จะค้นหาชื่อของพวกเขาในมุมมองตาราง [d]แถบสัญลักษณ์สำเนียงของพวกเขาในระหว่างการวินิจฉัย ดังนั้นเพรดิเคตของ@"name LIKE[CD] %@", object.nameตำแหน่งที่object.name == @"voodoo"จะส่งคืนอ็อบเจ็กต์ที่มีชื่อVòódòó

จากเอกสารแอปเปิ้ล: เช่น [CD] หมายถึง“ CASE- และออกเสียงตายเหมือน”) สำหรับคำอธิบายที่สมบูรณ์ของไวยากรณ์สตริงและรายชื่อของผู้ประกอบการทั้งหมดที่มีอยู่ให้ดูรูปแบบกริยา String ไวยากรณ์



3

NSPredicate มีเฉพาะใน iPhone 3.0

คุณจะไม่สังเกตเห็นสิ่งนั้นจนกว่าจะพยายามเรียกใช้บนอุปกรณ์


0

ด้วย Swift 3 เมื่อคุณต้องการกรองอาร์เรย์ของพจนานุกรมที่มีเพรดิเคตตามคีย์และค่าพจนานุกรมคุณสามารถเลือกรูปแบบใดรูปแบบหนึ่งต่อไปนี้


# 1. ใช้NSPredicate init(format:arguments:)initializer

หากคุณมาจาก 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:)initializer

อีกทางเลือกหนึ่งหากคุณต้องการAPI ที่พิมพ์มากเกินไปมากกว่าAPI ที่พิมพ์แบบสตริงคุณสามารถใช้init(block:)initializer ได้

การใช้งาน:

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 == '%@')"


ฉันคิดว่านั่นคือสิ่งที่มันพูดเช่นกัน เห็นได้ชัดว่าไม่จำเป็นต้องใช้เครื่องหมายคำพูด ฉันไม่แน่ใจว่าคู่มือบอกว่า "ควร" ใช้เพื่ออะไร
Corey Floyd
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.