Swift Dictionary: Pobierz wartości jako tablicę

150

Mam słownik zawierający UIColorobiekty zhaszowane przez wartość wyliczenia ColorScheme:

var colorsForColorScheme: [ColorScheme : UIColor] = ...

Chciałbym móc wyodrębnić tablicę wszystkich kolorów (wartości) zawartych w tym słowniku. Pomyślałem, że mogę użyć tej valueswłaściwości, która jest używana podczas iteracji po wartościach słownikowych ( for value in dictionary.values {...}), ale zwraca to błąd:

let colors: [UIColor] = colorsForColorSchemes.values
                        ~~~~~~~~~~~~~~~~~~~~~^~~~~~~
'LazyBidrectionalCollection<MapCollectionView<Dictionary<ColorScheme, UIColor>, UIColor>>' is not convertible to 'UIColor'

Wydaje się, że zamiast zwracać Arraywartości, valuesmetoda zwraca bardziej abstrakcyjny typ kolekcji. Czy istnieje sposób na uzyskanie wartości Arrayze słownika bez wyodrębniania ich w for-inpętli?

Stuart
źródło
1
Swift 5: colorsForColorSchemes.values
Juan Boero

Odpowiedzi:

284

Jak Swift 2.0 Dictionary„s valueswłaściwość teraz zwraca LazyMapCollectionzamiast LazyBidirectionalCollection. ArrayTyp umie zainicjować się przy użyciu tego rodzaju abstrakcyjne kolekcji:

let colors = Array(colorsForColorSchemes.values)

Wnioskowanie o typie Swifta już wie, że te wartości są UIColorobiektami, więc nie jest wymagane rzutowanie typów, co jest miłe!

Stuart
źródło
1
możesz również rzutować go jako tablicę z wpisanymi obiektami. działa świetnie! dzięki niech kolory = [CustomColorObject] (
colorsForColorSchemes.values
6
Wygląda na to, że w Swift 2.0 Dictionary.values ​​zwracają teraz LazyMapCollection w przeciwieństwie do LazyBidirectionalCollection. Niestety .array nie jest zdefiniowana w LazyMapCollection. Jednak sposób Array (Dictionary.values) nadal działa dobrze, ponieważ typy tablicowe wiedzą, jak zainicjować się z LazyMapCollection.
Tod Cunningham
8
Zwróć uwagę, że kolejność wartości może być nieoczekiwana. Na przykład [0: "small", 1: "medium", 2: "large"]prawdopodobnie NIE wygeneruje["small", "medium", "large"]
Simon Bengtsson
55

Możesz odwzorować słownik na tablicę wartości:

let colors = colorsForColorScheme.map { $0.1 }

Closure pobiera krotkę klucz-wartość ze słownika i zwraca tylko wartość. Zatem funkcja map generuje tablicę wartości.

Bardziej czytelna wersja tego samego kodu:

let colors = colorsForColorScheme.map { (scheme, color) in
    return color
}

AKTUALIZACJA

Od Xcode 9.0 można uzyskać dostęp do wartości słownika za pomocą valueswłaściwości, która jest zgodna z Collectionprotokołem:

let colors = colorsForColorScheme.values

Zwykle chcesz go po prostu jako tablicę:

let colors = Array(dict.values)

i to wszystko.

pjuzeliunas
źródło
2
Ale w rzeczywistości jest to czytelny sposób na uzyskanie tablicy let colors = Array (
colorsForColorScheme.values
1
uwielbiam to rozwiązanie
Navy Seal
@pjuzeliunas, ponieważ jest to najlepsza odpowiedź tutaj, właśnie zredagowałem ją w najnowszej wersji na 2020 r. oczywiście odpręż się, edytuj itp! okrzyki i dzięki!
Fattie
10

Posługiwać się colorsForColorScheme.map({$0.value})

Vishal kundaliya
źródło
8

możesz utworzyć rozszerzenie na LazyMapCollection

public extension LazyMapCollection  {

    func toArray() -> [Element]{
        return Array(self)
    }
}

colorsForColorSchemes.values.toArray() lub colorsForColorSchemes.keys.toArray()

GSerjo
źródło
3

Po pierwsze, z poniższego stwierdzenia wynika, że ​​nazwa zmiennej (słownika) to colorsForColorScheme

var colorsForColorScheme: [ColorScheme : UIColor] = ... 

podczas próby pobrania wartości ze colorsForColorSchemessłownika, kiedy to zrobiłeś-

let colors: [UIColor] = colorsForColorSchemes.values

co powinno spowodować błąd czasu kompilacji. W każdym razie zakładam, że miałeś literówkę, a nazwa słownika to colorsForColorSchemes. Oto rozwiązanie-

Jak wspomniano wcześniej, ze względu na właściwość wnioskowania o typie w swift, kod może wywnioskować, że typ zwracany przez .valuesfunkcję zwraca tablicę UIColor. Jednak Swift chce być bezpieczny dla typów, więc kiedy przechowujesz wartości w colorstablicy, musisz to jawnie zdefiniować. W przypadku Swift 5 i nowszych możesz po prostu wykonać następujące czynności:

let colors = [UIColor](colorsForColorSchemes.values)
Natasza
źródło