2

I'm trying to learn the wonderful world of NSPredicate, but am failing on practical application. Any guidance is appreciated.

In particular, I want to use NSPredicate to filter an array of Dictionaries. For example, take the following array and filter it down to just those entries where "species" == "dog".

 var arrayofDictionary:[[String:String]] = [

      ["name": "Ben", "species": "human"], 
      ["name": "Harp", "species": "dog"], 
      ["name": "Guinness", "species": "dog"]

 ]

Now I know how to filter the following way, but my understanding is this is the "lazy" way to do it and will not run as fast when doing large computations:

 let filteredArray = arrayofDictionary.filter { $0["species"] == "dog" }.flatMap { $0 }

So I have been playing around with NSPredicate, and feel like the following may be a good starting place, but am not sure how to use it next. Also, perhaps this only works for an array and not dictionaries?

 let speciesPredicate = NSPredicate(format: "species == %@", "dog")

Thanks for your help!


I was only able to find guidance on this in Objective-C here. Unfortunately I only am starting to pick up Swift.

This was a good tutorial on NSPredicate to start to get my head wrapped around it, but I couldn't figure out how to fully implement for the case mentioned above.

Community
  • 1
  • 1
Ben
  • 3,346
  • 6
  • 32
  • 51
  • 2
    Where have you heard that using swift closures *"is the "lazy" way to do it and will not run as fast when doing large computations"*? I would ALWAYS go for closures, they are typesafe and not prone to refactoring errors. But I think you can and should drop the `flatMap`. – luk2302 May 25 '16 at 20:23
  • Thanks for the feedback! What does flatMap do exactly? Just curious why you recommend to drop it. Cheers! – Ben May 26 '16 at 13:58

2 Answers2

5

Please check this out

var customerNameDict = ["firstName":"karthi","LastName":"alagu","MiddleName":"prabhu"];
var clientNameDict = ["firstName":"Selva","LastName":"kumar","MiddleName":"m"];
var employeeNameDict = ["firstName":"karthi","LastName":"prabhu","MiddleName":"kp"];


var attributeValue = "karthi";
var arrNames:Array = [customerNameDict,clientNameDict,employeeNameDict];
var namePredicate =NSPredicate(format: "firstName like %@",attributeValue);


let filteredArray = arrNames.filter { namePredicate.evaluateWithObject($0) };
println("names = ,\(filteredArray)");
Sachin Nikumbh
  • 911
  • 11
  • 11
1

I agree with the comment by @luk2302, in that using the Swift Array filter method is nicer in general than filtering with an NSPredicate. If you're worried about performance across a large data set you should have your content in CoreData and use an NSPredicate as part of an NSFetchRequest with proper indexing setup in your data model.

Having said that, filtering by NSPredicate is not explicitly supporting with the Swift Array type, so you would have to cast to NSArray to use it. It would look something like this:

let filteredArray = (arrayofDictionary as NSArray).filteredArrayUsingPredicate(speciesPredicate)
Charles A.
  • 10,685
  • 1
  • 42
  • 39
  • Thanks for the feedback. That approached worked perfectly. Based on your feedback and luk2302 I am going to go with the closure filter. If I run into performance issues at some point then will revisit NSPredicate. – Ben May 26 '16 at 02:14