Amit Erandole
Amit Erandole

Reputation: 12281

Filter an array of dictionaries

I have some data that mocks an api call like this:

 var people:Array<Dictionary<String, AnyObject>> = [
     ["name":"harry", "age": 28, "employed": true, "married": true],
     ["name":"larry", "age": 19, "employed": true, "married": true],
     ["name":"rachel", "age": 23, "employed": false, "married": false]
 ]

I want to iterate over this data and return a result that contains only married people above twenty. How do I do this? I tried starting like this:

var adults:Array = []

for person in people {
    for(key:String, value:AnyObject) in person {
        println(person["age"])
    }
}

But then got stuck on how to proceed. Also I wanted to use a map closure. How would I do this?

Upvotes: 1

Views: 303

Answers (4)

Imanou Petit
Imanou Petit

Reputation: 92599

With Swift 5, Array, like any type that conforms to Sequence protocol, has a method called filter(_:). filter(_:) has the following declaration:

func filter(_ isIncluded: (Self.Element) throws -> Bool) rethrows -> [Self.Element]

Returns an array containing, in order, the elements of the sequence that satisfy the given predicate.


The following Playground codes show how to use filter(_:) in order to filter your array with the desired predicate:

let people: [[String : Any]] = [
    ["name" : "harry", "age" : 28, "employed" : true, "married" : true],
    ["name" : "larry", "age" : 19, "employed" : true, "married" : true],
    ["name" : "rachel", "age" : 23, "employed" : false, "married" : false]
]

let filterClosure = { (personDictionary: [String : Any]) -> Bool in
    guard let marriedBool = personDictionary["married"] as? Bool, let validAgeBool = personDictionary["age"] as? Int  else { return false }
    return marriedBool == true && validAgeBool > 20
}

let filteredPeople = people.filter(filterClosure)

print(filteredPeople)
/*
 prints:
 [["name": "harry", "age": 28, "employed": true, "married": true]]
 */

Upvotes: 0

David Berry
David Berry

Reputation: 41246

Try:

let old = people.filter { person in
    return (person["married"] as NSNumber).boolValue && (person["age"] as NSNumber).intValue > 20
}

Since you use AnyObject, you have to use them as NSNumbers

Or, you can change your declaration to Array<Dictionary<String,Any>> and use:

let old = people.filter { person in
    return person["married"] as Bool && person["age"] as Int > 20
}

Upvotes: 0

rob mayoff
rob mayoff

Reputation: 386038

let adults = people.filter { person in
    return person["married"] as Bool && person["age"] as Int > 20
}

Upvotes: 2

Joshua Weinberg
Joshua Weinberg

Reputation: 28688

var people: Array<Dictionary<String, Any>> = [
    ["name":"harry", "age": 28, "employed": true, "married": true],
    ["name":"larry", "age": 19, "employed": true, "married": true],
    ["name":"rachel", "age": 23, "employed": false, "married": false]
]

let oldMarriedPeople = filter(people) { (person: Dictionary<String, Any>) -> Bool in
        let age = person["age"] as Int
        let married = person["married"] as Bool
        return age > 20 && married
}

for p in oldMarriedPeople {
    println(p)
}

Upvotes: 3

Related Questions