Dicionário Swift: obter valores como matriz

150

Eu tenho um dicionário que contém UIColorobjetos com hash por um valor de enumeração ColorScheme:

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

Gostaria de poder extrair uma matriz de todas as cores (os valores) contidas neste dicionário. Eu pensei que poderia usar a valuespropriedade, como é usada ao iterar sobre valores de dicionário ( for value in dictionary.values {...}), mas isso retorna um erro:

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

Parece que, em vez de retornar um Arraydos valores, o valuesmétodo retorna um tipo de coleção mais abstrato. Existe uma maneira de obter um Arraycontendo os valores do dicionário sem extraí-los em um for-inloop?

Stuart
fonte
1
Swift 5: colorsForColorSchemes.values
Juan Boero

Respostas:

284

A partir do Swift 2.0, Dictionarya valuespropriedade agora retorna a em LazyMapCollectionvez de a LazyBidirectionalCollection. O Arraytipo sabe como se inicializar usando este tipo de coleção abstrata:

let colors = Array(colorsForColorSchemes.values)

A inferência de tipo de Swift já sabe que esses valores são UIColorobjetos, portanto, nenhuma conversão de tipo é necessária, o que é bom!

Stuart
fonte
1
você também pode convertê-lo como uma matriz com objetos digitados. funciona bem! graças deixar cores = [CustomColorObject] (colorsForColorSchemes.values)
bolnad
6
Parece que no Swift 2.0, Dictionary.values ​​agora retorna um LazyMapCollection, em oposição a LazyBidirectionalCollection. Infelizmente, .array não está definido em um LazyMapCollection. No entanto, a maneira Array (dictionary.values) ainda funciona bem, pois os tipos de matriz sabem como se inicializar a partir de um LazyMapCollection.
Tod Cunningham
8
Observe que a ordem dos valores pode ser inesperada. Por exemplo [0: "small", 1: "medium", 2: "large"], provavelmente não gerar["small", "medium", "large"]
Simon Bengtsson
55

Você pode mapear o dicionário para uma matriz de valores:

let colors = colorsForColorScheme.map { $0.1 }

Closure pega uma tupla de valor-chave do dicionário e retorna apenas um valor. Portanto, a função map produz uma matriz de valores.

Versão mais legível do mesmo código:

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

ATUALIZAR

No Xcode 9.0, os valores do dicionário podem ser acessados ​​usando a valuespropriedade, que está em conformidade com o Collectionprotocolo:

let colors = colorsForColorScheme.values

Normalmente você só quer isso como uma matriz:

let colors = Array(dict.values)

e é isso.

pjuzeliunas
fonte
2
Mas, na verdade, esta é a maneira legível para obter variedade deixá cores = array (colorsForColorScheme.values)
Renetik
1
adoro esta solução #
Navy Seal #:
@pjuzeliunas, já que esta é a melhor resposta aqui, acabei de editar na última para 2020. obviamente, descontraia, edite etc! Saúde e obrigado!
Fattie 4/03
10

Usar colorsForColorScheme.map({$0.value})

Vishal kundaliya
fonte
8

você pode criar uma extensão em LazyMapCollection

public extension LazyMapCollection  {

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

colorsForColorSchemes.values.toArray() ou colorsForColorSchemes.keys.toArray()

GSerjo
fonte
3

Em primeiro lugar, a partir da seguinte declaração, parece que o nome da sua variável (dicionário) é colorsForColorScheme

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

enquanto você tenta obter os valores do colorsForColorSchemesdicionário quando você

let colors: [UIColor] = colorsForColorSchemes.values

o que deve gerar um erro de tempo de compilação. De qualquer forma, estou assumindo que você cometeu um erro de digitação e o nome do seu dicionário é colorsForColorSchemes. Então, aqui está a solução

Como mencionado anteriormente, devido à propriedade de inferência de tipo em swift, seu código pode inferir que o tipo retornado da .valuesfunção está retornando uma matriz de UIColor. No entanto, o Swift quer ser seguro quanto ao tipo, portanto, quando você armazena os valores na colorsmatriz, precisa defini-lo explicitamente. Para o Swift 5 e superior, agora você pode fazer o seguinte:

let colors = [UIColor](colorsForColorSchemes.values)
Natasha
fonte