arrays - 扩展 Swift 数组以按类型过滤元素

标签 arrays swift generics swift-extensions

如何扩展 swift 数组以访问特定类型的成员?

如果一个数组包含继承自同一个父类(super class)的多个类的实例,这就是相关的。理想情况下,它会适本地执行类型检查。


一些不太行得通的想法和事情:

使用 filter(_:) 方法工作正常,但确实强制类型安全。例如:

protocol MyProtocol { }
struct TypeA: MyProtocol { }
struct TypeB: MyProtocol { }

let myStructs:[MyProtocol] = [ TypeA(), TypeA(), TypeB() ]

let filteredArray = myStructs.filter({ $0 is TypeA })

filteredArray 包含正确的值,但类型仍然是 [MyProtocol] 而不是 [TypeA]。我希望将最后一个替换为 let filteredArray = myStructs.filter({ $0 is TypeA }) as! [TypeA] 会解决这个问题,但项目因 EXEC_BAD_INSTRUCTION 而失败,我不明白。也许类型转换数组是不可能的?

理想情况下,此行为可以包含在数组扩展中。以下不编译:

extension Array {
    func objectsOfType<T:Element>(type:T.Type) -> [T] {
        return filter { $0 is T } as! [T]
    }
}

这里似乎至少有两个问题:类型约束 T:Element 似乎不起作用。我不确定基于泛型类型添加约束的正确方法是什么。我在这里的意图是说 TElement 的子类型。此外,第 3 行存在编译时错误,但这可能只是传播相同的错误。

最佳答案

SequenceType 有一个 flatMap() 方法作为“可选过滤器”:

extension SequenceType {
    /// Return an `Array` containing the non-nil results of mapping
    /// `transform` over `self`.
    ///
    /// - Complexity: O(*M* + *N*), where *M* is the length of `self`
    ///   and *N* is the length of the result.
    @warn_unused_result
    @rethrows public func flatMap<T>(@noescape transform: (Self.Generator.Element) throws -> T?) rethrows -> [T]
}

结合 matt 的建议使用 as? 而不是 is 你 可以用作

let myStructs:[MyProtocol] = [ TypeA(), TypeA(), TypeB() ]
let filteredArray = myStructs.flatMap { $0 as? TypeA }

现在 filteredArray 的类型被推断为 [TypeA]

作为一种扩展方法,它会是

extension Array {
    func objectsOfType<T>(type:T.Type) -> [T] {
        return flatMap { $0 as? T }
    }
}

let filteredArray = myStructs.objectsOfType(TypeA.self)

注意:对于 Swift >= 4.1,flatMap 替换为 compactMap

关于arrays - 扩展 Swift 数组以按类型过滤元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33112114/

相关文章:

uitableview - swift - 错误 : unexpectedly found nil while unwrapping an optional value

swift - 为什么子协议(protocol)不满足其父协议(protocol)的一致性?

java - 枚举作为类中的泛型类型,但使用方法需要显式强制转换

java - 将 Java 泛型与 HashMap 结合使用

java - 如何在单独的行上输出字符串数组,每行允许有 N 个字符

C编程: Delete specific value stored in Array

arrays - 过滤 coffeescript 中的记录数组以返回年龄 > 50 的所有记录

arrays - 如何在 Swift 3.0 中将动态大小的二维数组填充为 X x 4 二维数组?

swift - 无法使用 Realm 存档 Swift OSX 应用程序

java - 仅包含一种类型的集合