user1960169
user1960169

Reputation: 3653

How to filter an array using NSPredicate in swift 3

I have an arraycontaining several dictionaries.

{
   DisplayName?:"Name of the employee"
   Age:28
   Department:"Dept 2"
}

I just converted my objective-c code into swift and trying to filter like this.

let exists = NSPredicate(format: "DisplayName2 CONTAINS[cd] \(searchText!)")
    let aList: Array<Any> = arrayDirectory.filter { exists.evaluate(with: $0) }
    if(aList.count>0)
    {
        arrayDirectory=aList
        facesCarousel.reloadData()
    }

But I am always getting the aList count as 0. It seems like not filtering my array. How can I write proper NSPredicatein swift 3 and filter my array using it.

Upvotes: 1

Views: 19230

Answers (5)

Gangireddy Rami Reddy
Gangireddy Rami Reddy

Reputation: 989

Use this code its worked fine in my side I hope this code will be help you

I have an array that array containing several dictionaries. Structure will be like this

 [
 {
  DisplayName:"Name of the employee1"
  Age:28
  Department:"Dept 2"
 }
 ]

In above array i am filtering with displayName key using apple search controller with help of predicate method

  func updateSearchResults(for searchController: UISearchController) {

    if (searchController.searchBar.text?.characters.count)! > 0 {
        guard let searchText = searchController.searchBar.text, searchText != "" else {
            return
        }

        let searchPredicate = NSPredicate(format: "DisplayName CONTAINS[C] %@", searchText)

        usersDataFromResponse = (filteredArray as NSArray).filtered(using: searchPredicate)

        print ("array = \(usersDataFromResponse)")

        self.tableview.reloadData()
    }


}

Upvotes: 0

Fogmeister
Fogmeister

Reputation: 77621

To make this filter in Swift doesn't require NSPredicate at all.

let array = arrayDirectory.filter {
    guard let name = $0["DisplayName"] as? String else {
        return false
    }
    return name.contains(searchText) 
}

That should be all you need.

EDIT

Updated to match your dictionary. I think this is what you're doing.

Ideally, you shouldn't be using a standard Dictionary as a working object. Convert your array of dictionaries to an array of Structs. That way you don't need to stringly type your code or unwrap properties that aren't really optional.

Workaround for working with an [Any] array...

Because you have defined your array as [Any] (don't do this) you will need to convert the object to a dictionary first.

let array = arrayDirectory.filter {
    guard let dictionary = $0 as? [String: Any],
        let name = dictionary["DisplayName"] as? String else {
        return false
    }
    return name.contains(searchText) 
}

Upvotes: 6

vadian
vadian

Reputation: 285059

The native Swift equivalent to the ObjC code is

let filteredArray = arrayDirectory.filter { ($0["displayName2"] as! String).range(of: searchText!, options: [.diacriticInsensitive, .caseInsensitive]) != nil }

assuming arrayDirectory is a native Swift Array. It considers also the case insensitive and diacritic insensitive parameters.

Upvotes: 4

Vidhi Patel
Vidhi Patel

Reputation: 641

Use this code my code will help you

let predicate = NSPredicate(format: "DisplayName2 contains[c] %@", textField.text!)
 let arr : NSArray = arrayDirectory.filtered(using: predicate) as NSArray
 if arr.count > 0
 {
    arrayDirectory=arr
    facesCarousel.reloadData()
 }

Upvotes: 0

Enamul Haque
Enamul Haque

Reputation: 5053

you can try

self.arrayDirectory.filter({(($0["Age"] as! String).localizedCaseInsensitiveContains(searchText))!})

Upvotes: 4

Related Questions