2016-06-16 8 views
5

Mam protokół "VariousThings" i dwie klasy, które są zgodne z nim, "ThingType1" i "ThingType2". Umieściłem kilka obiektów tych dwóch typów klas w tablicy zawierającej "Różne rzeczy". Teraz chcę po prostu wziąć wszystkie obiekty z tej tablicy, które są typu klasy "ThingType2" na przykład. Jak mogę to zrobić?W Swift, jak mogę filtrować tablicę obiektów zgodnych z protokołem według ich klasy?

Oto co mam do tej pory:

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) 

Odpowiedz

6

użyłbym flatMap zamiast filter tutaj, aby zapewnić Ci lepsze bezpieczeństwo typu. Można użyć warunkowego downcasta w celu odfiltrowania żądanych elementów i generycznych w celu zachowania informacji o typie. Wykorzystuje to fakt, że flatMap może odfiltrować wyniki nil z funkcji transformacji.

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] 

Teraz tablica Ci wyjść z funkcji itemsMatchingType jest [ThingType1] jeśli przejdą w ThingType1, zamiast po prostu [VariousThings]. W ten sposób nie będziesz musiał zajmować się brzydkimi, wymuszonymi przygnębieniami w dalszej części gry.

Jeśli naprawdę chciał się wyobraźnia, można również usunąć typ argumentu i pozwól Swift wywnioskować typy odfiltrować za pomocą wyraźnego typu adnotacji:

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

let justThingTypes1 : [ThingType1] = itemsMatchingType() 
+0

'.self' w rzeczywistości nie jest potrzebny. – vadian

+0

Nice one również =) –

+0

Dobra rada w sprawie płaskiego mapowania i powrotu T –

1

Można użyć filter dla tego:

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

Wadą tej metody jest że * wiesz *, że wynikowa tablica zawiera tylko elementy typu 'ThingType1', ale jeśli chodzi o kompilator, to po prostu odpowiadają one' VariousTypes'. –

3

można użyć generycznych

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

Doskonały, dzięki! –

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

Lepiej, jeśli potrafisz wyjaśnić, na czym polega rozwiązanie, zamiast prezentować je jako samodzielne. Wtedy inni będą mogli zrozumieć twoją odpowiedź. – AlBlue

Powiązane problemy