Filtering a Swift [AnyObject] array by type Filtering a Swift [AnyObject] array by type swift swift

Filtering a Swift [AnyObject] array by type


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 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." Rob Mayoff notes that if Optionals were SequenceTypes, which they probably should be, this would be a sensible name.)


I'd say that test 1 failing is clearly a compiler bug. In fact it crashes in the REPL:

Welcome to Apple Swift version 2.0 (700.1.100.2 700.1.74). Type :help for assistance.  1> import Foundation  2> let grabBag: [AnyObject] = [ "Tom", 4, "Dick", NSObject(), "Harry" ]grabBag: [AnyObject] = 5 values {  [0] = "Tom"  [1] = Int64(4)  [2] = "Dick"  [3] = {    isa = NSObject  }  [4] = "Harry"}  3> let strings = grabBag.filter { $0 is String } as! Stringstrings: String = {  _core = {    _baseAddress =    _countAndFlags =    _owner = <extracting data from value failed>  }}Execution interrupted. Enter Swift code to recover and continue.Enter LLDB commands to investigate (type :help for assistance.)4> :bt* thread #1: tid = 0x501bac, 0x00000001005c41f4 $__lldb_expr12`main + 420 at repl.swift:3, queue = 'com.apple.main-thread', stop reason = EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)  * frame #0: 0x00000001005c41f4 $__lldb_expr12`main + 420 at repl.swift:3    frame #1: 0x0000000100001420 repl_swift`_mh_execute_header + 5152    frame #2: 0x00007fff8dd725c9 libdyld.dylib`start + 1    frame #3: 0x00007fff8dd725c9 libdyld.dylib`start + 1

Anyway, as Rob Napier also answered, grabBag.flatMap { $0 as? String } is shorter and maybe simpler.