Swift4のDictionaryのアプデの目玉が公式ブログ?に掲載されてたので読んでみた
原文はこちら
Swift4ではDictionaryがより便利に使えるようになっているということで サンプルを見ていく
Grouping Values By a Key
Swift3系では
グループ機能がなく、かなりの手順を要していた
// Swift <= 3.1 var grouped: [GroceryItem.Department: [GroceryItem]] = [:] for item in groceries { if grouped[item.department] != nil { grouped[item.department]!.append(item) } else { grouped[item.department] = [item] } }
- まずグループの配列があるかチェック
- あれば配列についか
- なければ配列を作って
grouped
に登録
これがSwift4ではDictionaryのイニシャライザに用意され、1行で書くことができるようになりました。
// Swift >= 4.0 let groceriesByDepartment = Dictionary.init(grouping: groceries, by: { item in item.department })
このまま紹介しても味気ないので僕は下記のように使ってみました
extension Sequence { func group<Key>(by predicate: (Element) throws -> Key) rethrows -> [Key: [Element]] { return try Dictionary(grouping: self, by: predicate) } } let groceriesByDepartment = groceries.group(by: { item in item.department }) // [seafood: [{…}, {…}], bakery: [{…}, {…}], produce: [{…}, {…}, {…}]]
grouping対象はSequenceに準拠している必要があるということで、もはやSequeceに用意しちゃえばいいじゃん!と。
Transforming a Dictionary’s Values
Swift3まではmapすると、(key, value)
形式で走査してましたがmapValue
を使えば、valueだけを走査することができるようになりました。
なお、transformの対象はValueのみ。
let nameByDepartment = groceriesByDepartment.mapValues { items in items.map { item in item.name } } // [seafood: ["Salmon", "Shrimp"], bakery: ["Croissants", "Bread"], produce: ["Apples", "Bananas", "Grapes"]]
Uniquing Keys With
let pairs = [("dog", "🐕"), ("cat", "🐱"), ("dog", "🐶"), ("bunny", "🐰")] let petmoji = Dictionary(pairs, uniquingKeysWith: { (old, new) in new }) // petmoji["cat"] == "🐱" // petmoji["dog"] == "🐶"
SequenceのElementの型がCompound Typeなのでこちらはextensionかけない…
Using Default Values
for item in [🍌, 🍌, 🍞] { cart[item, default: 0] += 1 }
下記でも解説されてますね
Merging Two Dictionaries Into One
var cart = [🍌: 1, 🍇: 2] let otherCart = [🍌: 2, 🍇: 3] cart.merge(otherCart, uniquingKeysWith: +)
この実装見ていて初めて気づいたんですが、closureとしてオペレータ渡せるんですね。
知らなかったので今後の実装に使えそう。
func +(left: T, right: T) -> T { }
冷静に考えると、+ operatorはinfixな関数なので、なるほどSwiftよくできてるな〜と感心した案件でした。