2016-12-16 60 views
4

我连载一些JSON到对象中有failable JSON初始化器是这样的:地图只非空值

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

DynamicSection的init:

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

我只想追加一条通过的dynamicSections初始化部分。我怎样才能做到这一点?

可以使用filter + map

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

但是,这导致INITING的DynamicSection的两倍,这是我想避免的。有没有更好的方法来做到这一点?

回答

9

您可以使用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)] 

每当你看到一个链接filtermapflatMap一般可以作为一个很好的替代方法(不只是当使用过滤器检查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

谢谢!不知道flatMap(Foo.init),这很整齐。 –