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

时间:2022-09-06 22:57:54

I have a protocol, 'VariousThings', and two classes which conform to it, 'ThingType1' and 'ThingType2'. I've put some objects of these two types of classes into an array containing 'VariousThings'. I now want to just take all the objects out of that array that are of class type 'ThingType2' for example. How can I do this?

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

Here's what I have so far:

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

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 个解决方案

#1


9  

I would use flatMap instead of filter here in order to give you better type safety. You can use a conditional downcast to filter out the elements you want and generics in order to preserve type information. This takes advantage of the fact that flatMap can filter out nil results from the transform function.

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

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

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

let justThingTypes1 = itemsMatchingType(ThingType1.self) // of type [ThingType1]

Now the array you get out of your itemsMatchingType function is [ThingType1] if you pass in ThingType1, rather than simply [VariousThings]. That way you don't have to deal with ugly forced downcasts later down the line.

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

If you really wanted to get fancy, you could also remove the type argument and just let Swift infer the types to filter out via an explicit type annotation:

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

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

let justThingTypes1 : [ThingType1] = itemsMatchingType()

#2


3  

You could use a generic

你可以使用泛型

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

#3


1  

You can use the filter for this:

你可以使用过滤器:

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

#4


0  

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

#1


9  

I would use flatMap instead of filter here in order to give you better type safety. You can use a conditional downcast to filter out the elements you want and generics in order to preserve type information. This takes advantage of the fact that flatMap can filter out nil results from the transform function.

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

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

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

let justThingTypes1 = itemsMatchingType(ThingType1.self) // of type [ThingType1]

Now the array you get out of your itemsMatchingType function is [ThingType1] if you pass in ThingType1, rather than simply [VariousThings]. That way you don't have to deal with ugly forced downcasts later down the line.

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

If you really wanted to get fancy, you could also remove the type argument and just let Swift infer the types to filter out via an explicit type annotation:

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

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

let justThingTypes1 : [ThingType1] = itemsMatchingType()

#2


3  

You could use a generic

你可以使用泛型

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

#3


1  

You can use the filter for this:

你可以使用过滤器:

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

#4


0  

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