如何从[AnyObject]数组中过滤特定类型的对象

0 filter swift anyobject

是否可以过滤[AnyObject]数组以产生给定类型的所有元素,而不是其他元素?

如果类型在编译时已知,我可以这样做:

class MyClass1: CustomStringConvertible {

    var value: Int

    var description: String {
        return "MyClass1: \(value)"
    }

    init(_ value: Int) {
        self.value = value
    }
}

class MyClass2: CustomStringConvertible {

    var value: Int

    var description: String {
        return "MyClass1: \(value)"
    }

    init(_ value: Int) {
        self.value = value
    }
}

class MySubClass1: MyClass1 {
    override var description: String {
        return "MySubClass1: \(value)"
    }
}

let a1 = MySubClass1(1)
let a2 = MySubClass1(2)
let b1 = MyClass1(3)
let b2 = MyClass2(4)

let array: [AnyObject] = [a1, b1, a2, b2]

func getClass1ObjectsFromArray(_ array: [AnyObject]) -> [MyClass1] {
    return array.compactMap( { $0 as? MyClass1 })
}

func getSubClass1ObjectsFromArray(_ array: [AnyObject]) -> [MySubClass1] {
    return array.compactMap( { $0 as? MySubClass1 })
}

print(getClass1ObjectsFromArray(array))

print(getSubClass1ObjectsFromArray(array))
Run Code Online (Sandbox Code Playgroud)

打印:

[MySubClass1: 1, MyClass1: 3, MySubClass1: 2]
[MySubClass1: 1, MySubClass1: 2]
Run Code Online (Sandbox Code Playgroud)

对于我想要过滤的每种类型,我必须编写一个单独的函数.这看起来很丑陋,当选择的类型仅在运行时已知时,它将无法工作.

题:

是否有通用的方法来编写这样的函数?最好是:

func getObjectsOfType(_ type: TypeExpression, fromArray array: [AnyObject])
 -> [TypeExpression] {
     ... 
    }
Run Code Online (Sandbox Code Playgroud)

或任何其他方式来实现这一目标?

谢谢你的帮助!

Fog*_*ter 5

我想你可以用这样的东西......

let filteredArray = array.compactMap { $0 as? RequiredType }
Run Code Online (Sandbox Code Playgroud)

这将过滤数组并返回仅包含所需类型的类型化数组.

警告

话说回来.在Swift中,您应尽可能避免使用异构数组.数组实际上只应包含一种类型的项目.

一点代码测试......

在游乐场测试......

let array: [Any] = [1, "hello", 3, 3.1415, "world"]

let filteredArray = array.compactMap { $0 as? String }

filteredArray
Run Code Online (Sandbox Code Playgroud)

输出:

filteredArray = ["hello", "world"]
Run Code Online (Sandbox Code Playgroud)

编辑1

你也可以创建这样的泛型函数......

func filter<T>(array: [Any]) -> [T] {
    return array.compactMap { $0 as? T }
}

let filteredArray: [String] = filter(array: array)
Run Code Online (Sandbox Code Playgroud)

然后,它将根据您需要的输出数组的类型进行过滤.

我不确定你的意思只是在运行时知道你想要的类型.你能给出一个更具体的例子吗?

编辑2

另一种可能性是这样的通用功能......

func filter<T>(array: [Any], byType typeObject: T) -> [T] {
    return array.compactMap { $0 as? T }
}

let filteredArray = filter(array: array, byType: "some string")
Run Code Online (Sandbox Code Playgroud)

这使用第二个参数的类型信息按该类型的项过滤数组.

编辑3

如果您不喜欢传入该类型的实例,那么您可以传递该类型本身...

func filter<T>(array: [Any], byType typeObject: T.Type) -> [T] {
    return array.compactMap { $0 as? T }
}

let filteredArray = filter(array: array, byType: String.self)
Run Code Online (Sandbox Code Playgroud)

但是我不确定你从这里获得的更多东西,而不仅仅是首先用字符串过滤?

  • 如果你正在使用`[AnyObject]`,你几乎肯定会走上一条糟糕的道路.它属于"可以在Swift中完成的任务",但它超出了应该在Swift中完成的任务.几乎所有`AnyObject`的使用都在与Swift作斗争,并且有更好的解决方案(通常是枚举或协议). (2认同)