In Swift, how can I filter an array of objects matching the protocol by their class?

I have a protocol, "DifferentThings" and two classes that correspond to it, "ThingType1" and "ThingType2". I put some objects of these two types of classes into an array containing "DifferentThings". Now I want to just take all the objects from this array that are of the class type "ThingType2", for example. How can i do this?

Here is what I still have:

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) 
+5
source share
4 answers

I would use compactMap instead of filter to increase type safety. You can use conditional reduction to filter out the elements you want and generics to save type information. This exploits the fact that compactMap can filter nil results from the conversion function.

 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] 

Now the array that you get from your itemsMatchingType function is [ThingType1] if you pass ThingType1 , and not just [VariousThings] . This way, you wonโ€™t have to deal with ugly forced downs later.

+9
source

You can use generic

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

You can use filter for this:

 let justThingsTypes1 = array.filter { $0 is ThingType1 } 
+1
source
 let justThingTypes1: [VariousThings] = array.filter { variousThing in return Mirror(reflecting: variousThing).subjectType == ThingType1.self } 
0
source

All Articles