Pertanyaan Petakan hanya nilai non-nil


Saya membuat serialisasi json menjadi objek dengan inisialisasi json yang tersedia seperti ini:

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

Init DynamicSection:

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

Saya hanya ingin menambahkan DynamicSections yang meneruskan init ke bagian. Bagaimana saya bisa mencapai ini?

saya bisa menggunakan filter+map seperti

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

Tapi itu mengarah pada pencetus DynamicSection dua kali, yang ingin saya hindari. Apakah ada cara yang lebih baik untuk melakukan ini?


5
2017-12-16 10:15


asal


Jawaban:


Kamu dapat memakai flatMap:

return sectionJsons.flatMap { DynamicSection($0) }

Contoh:

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)]

Setiap kali Anda melihat rantai filter dan map, flatMap umumnya dapat digunakan sebagai pendekatan alternatif yang baik (tidak hanya ketika menggunakan filter untuk memeriksa nil entri).

Misalnya.

// 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)]

11
2017-12-16 10:20