Допустим, у меня есть такая модель:
enum UKCountry : String {
case england, scotland, wales, northernIreland
init?(placeName: String) {
// magic happens here
}
}
struct LocalPopulation {
let place: String
let population: Int
}
init(placeName:)
берет произвольную строку и выясняет, где она находится. Например, init(placeName: "London")
дает .england
. Как это происходит, не важно.
У меня также есть [LocalPopulation]
, который я хочу обработать. В частности, я хочу получить [UKCountry: [LocalPopulation]]
. Я мог бы сделать это:
let populations: [LocalPopulation] = [...]
let dict = Dictionary(grouping: populations, by: { UKCountry(placeName: $0.place)! })
Но не все места в populations
- это места в Великобритании, поэтому UKCountry.init
вернет nil
, и будет sh. Обратите внимание, что я не хочу ни одного места, которое не находится в Великобритании в результате. Я мог бы filter
сделать это заранее:
let populations: [LocalPopulation] = [...]
let filteredPopulations = populations.filter { UKCountry(placeName: $0.place) != nil }
let dict = Dictionary(grouping: populations, by: { UKCountry(placeName: $0.place)! })
Но это означает, что нужно запустить UKCountry.init
дважды. В зависимости от того, как это реализовано, это может быть дорогостоящим. Другой способ, о котором я подумал:
let populations: [LocalPopulation] = [...]
var dict = Dictionary(grouping: populations, by: { UKCountry(placeName: $0.place) })
dict[nil] = nil
let result = dict as! [UKCountry: [LocalPopulation]]
Но это немного "процедурно" ... Что еще раздражает, во всех вышеупомянутых попытках я использовал !
. Я знаю, что иногда !
неизбежно, но я бы хотел избежать этого, когда смогу.
Как я могу сделать это быстро?