post Image
Swift4.0でDictionaryが大幅にパワーアップした

Swift4.0でDictionaryがかなり使いやすくなったのでざっくり紹介したいと思います。
主にProposalsの内容なので詳しくはそちらを読んでください🙇

Sequenceタイプから初期化できる

init(uniqueKeysWithValues:)

Key-ValueのペアになったSequenceタイプからDictionaryを生成できるようになりました👏

let touples = [("Apple", 1), ("Orange", 2), ("Grape", 3)]

// ["Grape": 3, "Orange": 2, "Apple": 1]
let dictionary = Dictionary(uniqueKeysWithValues: touples)

上記のようにタプルだと要素が勝手に増やせてしまいKey-Valueの構成にならないので、
Swift3で入ったzipを使うとペアの値という縛りができます。

let names = ["Apple", "Orange", "Grape"]
let count = [1, 2, 3]
let ziped = zip(names, count)

// ["Grape": 3, "Orange": 2, "Apple": 1]
let dictionary = Dictionary(uniqueKeysWithValues: ziped)

また、重複したKeyを含めた場合は実行時エラーになるので注意です⚠️

let names = ["Apple", "Apple", "Grape"]
let count = [1, 2, 3]
let ziped = zip(names, count)

// Execution was interrupted, reason: EXC_BAD_INSTRUCTION
let dictionary = Dictionary(uniqueKeysWithValues: ziped)

重複したKey(Sequenceタイプ)に対して処理できる

init(_:uniquingKeysWith:)

上記のように重複したKeyがあった場合に何かしらの処理をしてそのKeyのValueとして初期化できます。

let names = ["Apple", "Apple", "Grape"]
let count = [1, 2, 3]
let ziped = zip(names, count)

// ["Grape": 3, "Apple": 3]
let merged = Dictionary(ziped, uniquingKeysWith: +)

merging(_:uniquingKeysWith:)

初期化だけでなく既にあるDictionaryに対しても行えるmergingmerge(mutating)も追加されています🙆

let dictionary = ["Grape": 3, "Orange": 2, "Apple": 1]

// ["Grape": 6, "Orange": 2, "Apple": 4]
let merged = dictionary.merging(ziped, uniquingKeysWith: +)

FilterやMapの扱いが楽になった

filter(_:)

CollectionタイプのfilterがDictionaryのメソッドとして実装されました。
今まではタプルの配列が返ってきたのですが、ちゃんとDictionaryで返ってきます👏

let dictionary = ["Grape": 3, "Orange": 2, "Apple": 1]

// Swift3: [(key: "Grape", value: 3), (key: "Orange", value: 2)]
// Swift4: ["Grape": 3, "Orange": 2]
let filterd = dictionary.filter { $0.value > 1 }

mapValues(_:)

DictionaryのValueに何かしらの処理を加えて新たなDictionaryを生成したいことって結構あると思います。
今までは下記のようにfor-inforEachでゴリゴリにやるしかありませんでした😭

let dictionary = ["Grape": 3, "Orange": 2, "Apple": 1]

var mapped = [String: Int]()
dictionary.forEach { touple in
    mapped[touple.key] = touple.value * 2
}

// ["Grape": 6, "Orange": 4, "Apple": 2]
mapped

上記を解決するためにmapValuesというメソッドが追加されました👏
これはDictionaryのValueだけをクロージャー内で受け取り、新しいValueが返り値になっています。
なんでKeyはないんだよって思うかもしれませんが、取り出しにくくなるだけで重複させる可能性もあるのでいらないですね。

let dictionary = ["Grape": 3, "Orange": 2, "Apple": 1]

// ["Grape": 6, "Orange": 4, "Apple": 2]
let mapped = dictionary.mapValues { $0 * 2 }

ValueをNon-Optionalに取り出せるようになった

subscript(_:default:)

DictionaryにKeyが存在しないValueを取り出した場合はnilになるのでNil Coalescing Operator(??)を使っていたと思います。
Swift4ではKeyと一緒にValueにデフォルト値を指定できるようになりました👏

let dictionary = ["Grape": 3, "Orange": 2, "Apple": 1]

// 4
let potato = dictionary["Potato", default: 4]

ただ上記ような例だとそこまでありがたみもなくNil Coalescing Operatorの方がいいと思います。
しかし+=などでValueの値を取り出してすぐにいじる場合はとても重宝すると思います。今までは…

let names = ["Apple", "Orange", "Apple", "Grape"]

var dictionary = [String: Int]()
names.forEach { name in

    // Binary operator '+=' cannot be applied to operands of type 'Int?' and 'Int'
    // dictionary[name] += 1

    let value = dictionary[name] ?? 0
    dictionary[name] = value + 1
}

// ["Grape": 1, "Orange": 1, "Apple": 2]
dictionary

上記のようにValueを一度Nil Coalescing Operatorで取り出してから処理しなくてはいけませんでした。
しかしデフォルト値を使えばこんなにスッキリ書けます👏

let names = ["Apple", "Orange", "Apple", "Grape"]

var dictionary = [String: Int]()
names.forEach { dictionary[$0, default: 0] += 1 }

// ["Grape": 1, "Orange": 1, "Apple": 2]
dictionary

GroupingしたDictionaryを簡単に生成できる

init(grouping:by:)

配列などのSequenceタイプから、クロージャー内で返した値をKeyにしたDictionaryを生成できます。今までは…

let names = ["Apple", "Grape", "Apricot", "Guava"]

var initialGroup = [Character: [String]]()
names.sorted().forEach { name in

    let character = name.characters.first ?? "#"
    var names = initialGroup[character] ?? []
    names.append(name)
    initialGroup[character] = names
}

// ["G": ["Grape", "Guava"], "A": ["Apple", "Apricot"]]
initialGroup

上記のようにとても面倒だったのですが、たった数行で頭文字や文字数ごとに分けるなどができてかなり便利です👏

let names = ["Apple", "Grape", "Apricot", "Guava"]

// ["G": ["Grape", "Guava"], "A": ["Apple", "Apricot"]]
let initialGroup = Dictionary(grouping: names) { $0.first ?? "#" }

// [5: ["Apple", "Grape", "Guava"], 7: ["Apricot"]]
let countGroup = Dictionary(grouping: names) { $0.count }

容量の指定ができる

reserveCapacity(_:)

Dictionaryで格納するデータ量が決まっている場合などに容量を指定できるようになりました。
reserveCapacityを使えば指定した容量(Backing Strageを含む: 1,3,6,12..)が確保されるのでパフォーマンスアップになります👏

var dictionary = [String: Int]()
print(dictionary.capacity) // 0

dictionary.reserveCapacity(4)
print(dictionary.capacity) // 6

dictionary.reserveCapacity(7)
print(dictionary.capacity) // 12

おしまい👋


『 Swift 』Article List
Category List

Eye Catch Image
Read More

Androidに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

AWSに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Bitcoinに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

CentOSに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

dockerに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

GitHubに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Goに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Javaに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

JavaScriptに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Laravelに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Pythonに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Rubyに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Scalaに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Swiftに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Unityに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Vue.jsに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Wordpressに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

機械学習に関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。