仅映射非零值

时间:2016-12-16 10:15:10

标签: swift

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

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

DynamicSection的初始化:

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

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

可以使用filter + map喜欢

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

但这导致两次启动DynamicSection,我想避免。有没有更好的方法呢?

2 个答案:

答案 0 :(得分:16)

您可以使用flatMap

return sectionJsons.flatMap { DynamicSection($0) }

示例:

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

每当您看到链式filtermap时,flatMap通常可以用作一种不错的替代方法(不仅仅是在使用过滤器检查nil条目时)

E.g。

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

答案 1 :(得分:1)

对于Swift 3.0及更高版本:

return sectionJsons.compactMap { DynamicSection($0) }