Say I have an array of AnyObject
.
let grabBag: [AnyObject] = [ "Tom", 4, "Dick", NSObject(), "Harry" ]
and I want to cast it to an array of Strings
, extracting only those elements that are in fact Strings
. I would expect this to work:
let strings = grabBag.filter{ $0 is String } as! [String] // 1
but it gives the error 'Bool' is not convertible to 'String'
. Yet this works:
let definitelyStrings = grabBag.filter{ $0 is String } // 2 let strings = definitelyStrings as! [String] //
Why does 2
work when 1
does not? And is there a simpler (than 2
) way of extracting and casting the elements of an [AnyObject]
to whatever [T]
?
One can use filter() function in JavaScript to filter the object array based on attributes. The filter() function will return a new array containing all the array elements that pass the given condition. If no elements pass the condition it returns an empty array.
When you apply a filter on an Array, the original Array is not modified. Instead, filter(isIncluded:) creates a new Array with only the elements you want.
It's better to use compactMap
for a nice one-liner:
let strings = grabBag.compactMap { $0 as? String }
Now strings
is of type [String]
.
This is what flatMap
is for:
let strings = grabBag.flatMap{ $0 as? String }
This takes a closure that returns an optional; if the optional is non-nil, then it is added to the result.
(Note that this doesn't match the meaning of Rob Mayoff notes that if Optionals were SequenceTypes, which they probably should be, this would be a sensible name.)flatMap
from other languages, and doesn't even match the other meaning of flatMap
in Swift. A better name would have been mapOptional
or mapSome
. But it's still kind of intuitive, even if inconsistent. It "maps to optionals, then flattens out all the nils."
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