I am serialising some json into objects with a failable json initialiser like this:
sections = {
let sectionJsons = json["sections"] as! [[String:AnyObject]]
return sectionJsons.map {
DynamicSection($0)
}
}()
DynamicSection's init:
init?(_ json:[String:AnyObject]) {
super.init()
//Boring stuff that can fail
I want to only append the DynamicSections that passed the init to sections. How can I accomplish this?
I can use filter
+map
like
return sectionJsons.filter { DynamicSection($0) != nil }.map { DynamicSection($0)! }
But that leads to initing the DynamicSection twice, which i'd like to avoid. Is there any better way to do this?
Syntax: Array. compact() Parameter: Array to remove the 'nil' value from. Return: removes all the nil values from the array.
compactMap helps you to eliminate nil values and map at the same time. It takes your sequence and produces a fancier sequence. Easy as it is. Here is the definition of compactMap . compactMap returns an array containing the non-nil results of calling the given transformation with each element of this sequence.
flatMap(hashtags) print(tags) // ["#swiftui", "#combine", "#wwdc"] So map transforms an array of values into an array of other values, and flatMap does the same thing, but also flattens a result of nested collections into just a single array.
You can use flatMap
:
return sectionJsons.flatMap { DynamicSection($0) }
Example:
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)]
Whenever you see a chained filter
and map
, flatMap
can generally be used as a good alternative approach (not just when using the filter to check nil
entries).
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)]
For Swift 3.0 and above:
return sectionJsons.compactMap { DynamicSection($0) }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With