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

时间:2016-06-16 11:23:04

标签: arrays swift class functional-programming

我有一个协议,' 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)

4 个答案:

答案 0 :(得分:9)

我会在这里使用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]

如果您传入itemsMatchingType,而不是简单[ThingType1],那么您从ThingType1函数中获取的数组为[VariousThings]。这样你就不必在以后处理丑陋的被迫向下倾斜。

答案 1 :(得分:3)

您可以使用通用

func itemsMatchingType<T : VariousThings>(type: T.Type) -> [VariousThings] {
  return array.filter { $0 is T }
}

答案 2 :(得分:1)

您可以使用filter

let justThingsTypes1 = array.filter { $0 is ThingType1 }

答案 3 :(得分:0)

let justThingTypes1: [VariousThings] = array.filter {
  variousThing in
  return Mirror(reflecting: variousThing).subjectType == ThingType1.self
}