仅映射非零值

Osc*_*and 10 swift

我正在使用像这样的可用json初始化器将一些json序列化为对象:

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

DynamicSection的init:

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

我只想将传递init的DynamicSections附加到section.我怎么能做到这一点?

可以filter+ map喜欢

return sectionJsons.filter { DynamicSection($0) != nil }.map { DynamicSection($0)! }
Run Code Online (Sandbox Code Playgroud)

但这导致两次启动DynamicSection,我想避免.有没有更好的方法来做到这一点?

pie*_*e23 21

对于 Swift 3.0 及更高版本:

return sectionJsons.compactMap { DynamicSection($0) }
Run Code Online (Sandbox Code Playgroud)


dfr*_*fri 16

你可以使用flatMap:

return sectionJsons.flatMap { DynamicSection($0) }
Run Code Online (Sandbox Code Playgroud)

例:

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)]
Run Code Online (Sandbox Code Playgroud)

每当你看到一个链接filtermap,flatMap一般可以作为一个很好的替代方法(不只是使用过滤器来检查时nil的条目).

例如

// 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)]
Run Code Online (Sandbox Code Playgroud)

  • 在Swift 4中“不推荐使用'flatMap':在闭包返回可选值的情况下,请使用compactMap(_ :)” (2认同)