Govaadiyo
Govaadiyo

Reputation: 6082

Best way to search result from array of dictionary

I'm new to Swift language so playing with Playground.

As my title saying what is the best way to search result from the array of the dictionary?

Ex.

Below is my Array I created for learning purpose.

let array = [
    ["name": "Amit", "age": "27", "rollno": 12],
    ["name": "Ananad", "age": "26", "rollno": 10],
    ["name": "Kashyap", "age": "25", "rollno": 11],
    ["name": "Raj", "age": "25", "rollno": 07],
    ["name": "Akshya", "age": "28", "rollno": 13]
]

And I want to search "name" based on user input. Look at below stuff what I have done.

let strSeach = "k"
let searchResult = myArray.filter{String(($0["name"] as! String).characters.prefix(strSeach.characters.count)).lowercased() == strSeach.lowercased()}

print("index => \(searchResult)")

Output is:

searchResult => [["rollno": 11, "name": "Kashyap", "age": "25"]]

But confusion, Is it right way to search? I used characters.prefix, lowercased() is it good or another best way?

and If I want to apply multiple searches like search by "name", "age" etc. then how can we achieve it in swift filter?

I think we can't use NSPredicate with Swift Array? otherwise, we can do it by following

let searchPredicate = NSPredicate(format: "name CONTAINS [c] %@ OR age CONTAINS [c]", strSeach)

Like that!

Upvotes: 0

Views: 111

Answers (4)

Luca Angeletti
Luca Angeletti

Reputation: 59496

You should use a Model Value

First of all you should define the following Model Value to represent your data

struct Person {

    let name: String
    let age: Int
    let rollno: Int

    init?(dict:[String:Any]) {
        guard
            let name = dict["name"] as? String,
            let ageText = dict["age"] as? String,
            let age = Int(ageText),
            let rollno = dict["rollno"] as? Int
            else { return nil}

        self.name = name
        self.age = age
        self.rollno = rollno
    }
}

Now, given your initial array

let data = [
    ["name": "Amit", "age": "27", "rollno": 12],
    ["name": "Ananad", "age": "26", "rollno": 10],
    ["name": "Kashyap", "age": "25", "rollno": 11],
    ["name": "Raj", "age": "25", "rollno": 07],
    ["name": "Akshya", "age": "28", "rollno": 13]
]

you can get an array of Person(s)

let persons = data.flatMap(Person.init)

Persons where name contains a String

Now the filtering part is trivial, look

let personsWhereNameContainsK = persons.filter { $0.name.lowercased().contains("k") }

Result

[
    Person(name: "Kashyap", age: 25, rollno: 11),
    Person(name: "Akshya", age: 28, rollno: 13)
]

Upvotes: 1

Prashant Tukadiya
Prashant Tukadiya

Reputation: 16436

With Filters

You can use this

let array = [
["name": "Amit", "age": "27", "rollno": 12],
["name": "Ananad", "age": "26", "rollno": 10],
["name": "Kashyap", "age": "25", "rollno": 11],
["name": "Raj", "age": "25", "rollno": 07],
["name": "Akshya", "age": "28", "rollno": 13]
]

let searchSting = "am"

var search = array.filter { ($0["name"] as!    String).lowercased().contains(searchSting.lowercased()) }

Output

[["rollno": 12, "name": "Amit", "age": "27"]]

WITH Predicates

let searchPredicate = NSPredicate(format: "name CONTAINS [c] %@ OR age == %@", searchSting)
search = array.filter { searchPredicate.evaluate(with: $0)}

OUTPUT

[["rollno": 12, "name": "Amit", "age": "27"]]

Upvotes: 1

Sweeper
Sweeper

Reputation: 271050

You can use NSPredicate if you want, but note that it is slower than filter.

You just need to convert your swift array to an NSArray then call filtered.

Also, here's another way of doing this using swift filter:

let searchResult = array.filter { 
    ($0["name"] as! String).lowercased().hasPrefix(strSeach.lowercased()) }

Upvotes: 1

Venk
Venk

Reputation: 5955

You can use contains keyword in the filter as follows,

let searchResult = myArray.filter{String(($0["name"] as! String).lowercased().contains(strSeach.lowercased())}

For Multiple filters (i am adding condition based on your predicate),

let searchResult = myArray.filter{(String(($0["name"] as! String).lowercased().contains(strSeach.lowercased())) || (String(($0["age"] as! String).lowercased().contains(strSeach.lowercased()))}

Upvotes: 0

Related Questions