0

I have this array:

class Filter {

    var key = ""
    var value = ""

    init(key: String, value: String) {
        self.key = key
        self.value = value
    }

}

let arry = [
    "a":[Filter(key:"city",value:"aachen"),Filter(key:"city",value:"augsburg")],
    "b":[Filter(key:"city",value:"bremen"),Filter(key:"city",value:"berlin")]
]

and I want to look for augsburg and remove it from the dictionary with the filter function so the output looks like this:

let arry = [
    "a":[Filter(key:"city",value:"aachen")],
    "b":[Filter(key:"city",value:"bremen"),Filter(key:"city",value:"berlin")]
]

I tried it with many filter and map constelations but I always get this structure as result:

let arry = [
    ["a":[Filter(key:"city",value:"aachen")]],
    ["b":[Filter(key:"city",value:"bremen"),Filter(key:"city",value:"berlin")]]
]

for example with this filter:

arry.map({ key,values in

    return [key:values.filter{$0.value != "augsburg"}]
})

What is the problem here? How can I filter and map over more complex objects?

Kingalione
  • 4,237
  • 6
  • 49
  • 84
  • First of all your array is dictionary and why are you making this so complex, don't you think instead of making class Filter with property key and value, you need to make it with first-character that contains the first later of city and second String array that holds all the city name for that object. – Nirav D Dec 25 '16 at 05:06
  • Related: http://stackoverflow.com/questions/24116271/whats-the-cleanest-way-of-applying-map-to-a-dictionary-in-swift. – Martin R Dec 25 '16 at 05:21

1 Answers1

1

Maybe one thing you should know is that map method of Dictionary returns Array, not Dictionary.

public func map<T>(_ transform: (Key, Value) throws -> T) rethrows -> [T]

So, if you want the filtered result as Dictionary, you may need to use reduce:

class Filter: CustomStringConvertible {

    var key = ""
    var value = ""

    init(key: String, value: String) {
        self.key = key
        self.value = value
    }

    //For debugging
    var description: String {
        return "<Filter: key=\(key), value=\(value)>"
    }
}

let dict = [
    "a":[Filter(key:"city",value:"aachen"),Filter(key:"city",value:"augsburg")],
    "b":[Filter(key:"city",value:"bremen"),Filter(key:"city",value:"berlin")]
]

let filteredDict = dict.reduce([:]) {tempDict, nextPair in
    var mutableDict = tempDict
    mutableDict[nextPair.key] = nextPair.value.filter {$0.value != "augsburg"}
    return mutableDict
}

(Generally, Swift Dictionary is a hash-table based implementation of associative array, but you should better avoid naming arry for Dictionary variables. Such naming is so confusing.)

Or else simply use for-in loop:

var resultDict: [String: [Filter]] = [:]
for (key, value) in dict {
    resultDict[key] = value.filter {$0.value != "augsburg"}
}
print(resultDict) //->["b": [<Filter: key=city, value=bremen>, <Filter: key=city, value=berlin>], "a": [<Filter: key=city, value=aachen>]]
OOPer
  • 47,149
  • 6
  • 107
  • 142
  • 3
    A for-in loop is preferable as it can mutate the resultant dictionary directly, whereas using `reduce` creates an intermediate dictionary for each iteration, making it run in quadratic, rather than linear time. – Hamish Dec 25 '16 at 12:25