2016-12-16 9 views
4

値私はこのようなfailable JSON初期化子とオブジェクトにいくつかのJSONを直列化しています:地図のみ非nilの

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を追加したいですセクションへのinit。どうすればこれを達成できますか?

私は

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

ようfilter + mapを使用することができますしかし、それは私が避けたいのですがどの、二回DynamicSectionをINITINGにつながります。これを行うための良い方法はありますか?

答えて

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

あなたがチェーン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)] 
+1

ありがとうございます! flatMap(Foo.init)について知りませんでした。 –