按类型过滤Swift [AnyObject]数组

Old*_*ier 18 arrays casting swift

说我有一个数组AnyObject.

let grabBag: [AnyObject] = [ "Tom", 4, "Dick", NSObject(), "Harry" ]
Run Code Online (Sandbox Code Playgroud)

我想将它转换为一个数组Strings,只提取那些实际上的元素Strings.我希望这可行:

let strings = grabBag.filter{ $0 is String } as! [String]      // 1
Run Code Online (Sandbox Code Playgroud)

但它给出了错误'Bool' is not convertible to 'String'.但这有效:

let definitelyStrings = grabBag.filter{ $0 is String }         // 2
let strings = definitelyStrings as! [String]                   //
Run Code Online (Sandbox Code Playgroud)

为什么不2工作1?而且是有一个更简单的(除2提取和铸造的元素)的方式[AnyObject],以什么[T]

aya*_*aio 30

最好使用flatMap一个漂亮的单线程:

let strings = grabBag.flatMap { $0 as? String }
Run Code Online (Sandbox Code Playgroud)

现在strings是类型[String].


更新:在Swift 4.2中你应该使用compactMap而不是flatMap:

let strings = grabBag.compactMap { $0 as? String }
Run Code Online (Sandbox Code Playgroud)


Rob*_*ier 8

flatMap是为了什么:

let strings = grabBag.flatMap{ $0 as? String }
Run Code Online (Sandbox Code Playgroud)

这需要一个返回可选的闭包; 如果optional是非nil,则将其添加到结果中.

(请注意,这flatMap与其他语言的含义不符,甚至与flatMapSwift 中的其他含义不匹配.更好的名称可能是mapOptionalmapSome.但它仍然是直观的,即使不一致.它"映射对于选项,然后扁平化所有的nils." Rob Mayoff指出,如果Optionals是序列类型,它们可能应该是,这将是一个明智的名称.)


rob*_*off 5

我想说测试 1 失败显然是编译器错误。事实上它在 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! String
strings: 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
Run Code Online (Sandbox Code Playgroud)

不管怎样,正如 Rob Napier 也回答的那样,grabBag.flatMap { $0 as? String }更短,也许更简单。