在Swift中,如何按类别过滤符合协议的对象数组?

Mar*_*ges 6 arrays functional-programming class swift

我有一个协议,'VariousThings',以及两个符合它的类,'ThingType1'和'ThingType2'.我把这两类类的一些对象放入一个包含'VariousThings'的数组中.我现在想要从该数组中取出所有类型为'ThingType2'的对象.我怎样才能做到这一点?

这是我到目前为止所拥有的:

protocol VariousThings: class {

}

class ThingType1: VariousThings {

}

class ThingType2: VariousThings {

}


let array: [VariousThings] = [ThingType1(), ThingType2()]


func itemsMatchingType(type: VariousThings.Type) -> [VariousThings] {
    return array.filter { variousThing in
        return (variousThing.self === type)
    }
}


let justThingTypes1: [VariousThings] = itemsMatchingType(ThingType1)
Run Code Online (Sandbox Code Playgroud)

Ham*_*ish 11

我会用compactMap而不是在filter这里为了给你更好的类型安全.您可以使用条件向下转换来过滤掉所需的元素和泛型,以便保留类型信息.这利用了compactMap可以过滤掉nil变换函数的结果的事实.

let array: [VariousThings] = [ThingType1(), ThingType2()]    

func itemsMatchingType<T : VariousThings>(_ type: T.Type) -> [T] {
  return array.compactMap { $0 as? T }
}

let justThingTypes1 = itemsMatchingType(ThingType1.self) // of type [ThingType1]
Run Code Online (Sandbox Code Playgroud)

现在你从itemsMatchingType函数中得到的数组就是[ThingType1]你传入的ThingType1,而不是简单的[VariousThings].通过这种方式,您不必在以后处理丑陋的强迫性向下倾斜.

如果你真的想要花哨,你也可以删除type参数,让Swift通过显式类型注释推断出要过滤掉的类型:

let array: [VariousThings] = [ThingType1(), ThingType2()]    

func itemsMatchingType<T : VariousThings>(_ type: T.Type) -> [T] {
  return array.compactMap { $0 as? T }
}

let justThingTypes1 = itemsMatchingType(ThingType1.self) // of type [ThingType1]
Run Code Online (Sandbox Code Playgroud)