/ / Mapovať iba hodnoty bez nuly - rýchle

Mapovať iba hodnoty bez nuly - rýchle

Serializujem nejaké json do objektov s neuskutočniteľným iniciátorom json takto:

 sections = {
let sectionJsons = json["sections"] as! [[String:AnyObject]]
return sectionJsons.map {
DynamicSection($0)
}
}()

Init služby DynamicSection:

init?(_ json:[String:AnyObject]) {
super.init()
//Boring stuff that can fail

Chcem pridať len DynamicSections, ktoré prešli init na sekcie. Ako to môžem dosiahnuť?

ja môcť použitie filter+map Páči sa mi to

return sectionJsons.filter { DynamicSection($0) != nil }.map { DynamicSection($0)! }

To však vedie k dvojnásobnému zapusteniu DynamicSection, ktorému sa chcem vyhnúť. Existuje nejaký lepší spôsob, ako to urobiť?

odpovede:

11 pre odpoveď č. 1

Môžeš použiť flatMap:

return sectionJsons.flatMap { DynamicSection($0) }

Príklad:

struct Foo {
let num: Int
init?(_ num: Int) {
guard num % 2 == 0 else { return nil }
self.num = num
}
}

let arr = Array(1...5) // odd numbers will fail "Foo" initialization
print(arr.flatMap { Foo($0) }) // [Foo(num: 2), Foo(num: 4)]

// or, point to "Foo.init" instead of using an anonymous closure
print(arr.flatMap(Foo.init))   // [Foo(num: 2), Foo(num: 4)]

Kedykoľvek uvidíte reťaze filter a map, flatMap môže byť vo všeobecnosti použitý ako dobrý alternatívny prístup (nielen pri použití filtra na kontrolu nil záznamov).

Napr.

// non-init-failable Foo
struct Foo {
let num: Int
init(_ num: Int) {
self.num = num
}
}

let arr = Array(1...5) // we only want to use the even numbers to initialize Foo"s

// chained filter and map
print(arr.filter { $0 % 2 == 0}.map { Foo($0) })   // [Foo(num: 2), Foo(num: 4)]

// or, with flatMap
print(arr.flatMap { $0 % 2 == 0 ? Foo($0) : nil }) // [Foo(num: 2), Foo(num: 4)]