2020/1/24 Swift ディクショナリ(Dictionaries)

ディクショナリは、データの集合の中のキー(key)とバリュー(value、値)の関連性を格納する型です。一つのディクショナリの中のキーは全て同じ型、一つのディクショナリの中の全てのバリュー(値)は同じ型です。それぞれのバリュー(値)は一意(ユニーク)なキーと関連づけられ、キーは、ディクショナリの中でバリューの識別子としての役割を果たします。配列(array)の要素と違い、ディクショナリの要素は順番がありません(indexを持たない。)。

識別子と関連づいた値を探したりする時はディクショナリを使いますが、それは現実世界で辞書で定義を探すときに、特定の単語により探そうとすることと一緒です。

ディクショナリの簡略記法

Swiftのディクショナリ型は、Dictionary<Key,Value>と表現されます。Keyはディクショナリのキーとして使用される値の型です。Valueは、そのキーに格納される値の型です。

NOTE

ディクショナリのキーの型はHashableプロトコルに準拠していなければなりません。

ディクショナリ型は簡略記法として

[Key:Value]

と記述できます。機能的には

Dictionary<Key,Value>

[Key:Value]

も同じものを表しますが、一般的に簡略記法が好まれ、このガイドでもディクショナリ型を表記するとき簡略記法を用います。


空のディクショナリを生成する 

配列と同様に、以下のようにイニシャライザ構文を用いて空のディクショナリを生成できます。

var namesOfIntegers = [Int: String]()
// namesOfIntegers is an empty [Int: String] dictionary

上記サンプルでは、Int型のキーに人の名前を格納するため、[Int:String]型の空のディクショナリを生成しています。

それまでのコードにより型の情報が推測できる場合、空のディクショナリリテラルを用いて空のディクショナリを生成することができます。空のディクショナリリテラルは

[:]

です。

namesOfIntegers[16] = "sixteen"
// namesOfIntegers now contains 1 key-value pair
namesOfIntegers = [:]
// namesOfIntegers is once again an empty dictionary of type [Int: String]

ディクショナリリテラルによりディクショナリを生成する

配列と似たリテラルの記述法により、ディクショナリリテラルを使ってディクショナリを生成できます。ディクショナリリテラルは、一つ、あるいは複数のキーバリューペアをDictionaryコレクションとして記述する簡略記法です。

キーバリューペアはキーと値のコンビです。ディクショナリリテラルの中でキーと値はコロンで区切ります。キーバリューペアはリストとして記述され、カンマで区切り、周りを角カッコ([ ])で囲みます。

[key 1: value 1, key 2: value 2, key 3: value 3]

下のサンプルは国際空港の名前を格納するディクショナリを生成しています。キーは三文字のInternational Air Transport Association codes、バリューは空港名です。

var airports: [String: String] = ["YYZ": "Toronto Pearson", "DUB": "Dublin"]

変数airportsにセットされるディクショナリは[String:String]型と型注釈されています。これは、「キーはString型、値もString型」であることを表現しています。

NOTE

airportsディクショナリは変数として宣言されています(varで宣言されている)。定数(letで宣言)ではありません。ですのでこの後のサンプルでairportsに要素を追加することが可能です。

airportsディクショナリは二つのキーバリューペアを含んだディクショナリリテラルにより初期化されています。一つ目のペアは「キー:”YYZ”、値:”Toronto Pearson”」です。二つ目のペアは「キー:”DUB”、値:”Dublin”」です。

このディクショナリリテラルには二つのString:Stringペアが含まれています。このキーバリューペアは変数airportsの宣言時の型注釈と一致します。ですので問題なく代入(初期化)できています。

変数への代入(初期化)時に代入するディクショナリリテラルにより変数の型が推定できる場合、配列と同様、型注釈は必要ありません。airports変数の初期化は以下のように書くこともできます。

var airports = ["YYZ": "Toronto Pearson", "DUB": "Dublin"]

上記で全てのキーは同じ型(String型)であり、全ての値も同じ型(String型)ですので、Swiftは、airports変数の型を[String:String]と型推定します。

ディクショナリへのアクセス・ディクショナリの修正

ディクショナリへのアクセス・ディクショナリの修正は、Dictionary<Key:Value>型で用意されているプロパティ・メソッドを用いる方法と、サブスクリプト構文を用いる方法があります。

配列と同様、ディクショナリの要素数は、読み取り専用のcountプロパティにより確認できます。

var airports = ["YYZ": "Toronto Pearson", "DUB": "Dublin"]
print("The airports dictionary contains \(airports.count) items.")
// Prints "The airports dictionary contains 2 items."

countプロパティの値が0である、ということはつまり要素数がゼロ、つまり空のディクショナリということですが、空のディクショナリかどうかを調べるのに、Bool型のisEmptyプロパティが使えます。

var airports = ["YYZ": "Toronto Pearson", "DUB": "Dublin"]
if airports.isEmpty {
    print("The airports dictionary is empty.")
} else {
    print("The airports dictionary is not empty.")
}
// Prints "The airports dictionary is not empty."

工事中🏗

 

特定のキーによりディクショナリの値を取得するのに、サブスクリプト構文を使うことができます。存在しないキーによる値の問い合わせが可能なため、ディクショナリのサブスクリプトはそのディクショナリの値の型のオプショナル型を返します。問い合わせたキーに対応する値が存在する場合、その値を含むオプショナル型を返します。そうでなければnilを返します。

var airports = ["YYZ": "Toronto Pearson", "DUB": "Dublin"]
if let airportName = airports["DUB"] {
    print("The name of the airport is \(airportName).")
} else {
    print("That airport is not in the airports dictionary.")
}
//The name of the airport is Dublin.

上記サンプルではオプショナルバインディングによりairportNameにはアンラップされたString型の値”Dublin”がセットされます。オプショナルバインディングについてはこちらをご覧ください。

サブスクリプト構文を使ってディクショナリからキーバリューペアを削除するには、以下のようにnilを代入します。

var airports = ["YYZ": "Toronto Pearson", "DUB": "Dublin"]
airports["APL"] = "Apple International"
// "Apple International" という空港はありませんので、要素を削除しましょう。
airports["APL"] = nil
// APL は、airportsディクショナリから削除されました。

if let airportName = airports["APL"] {
    print("The name of the airport is \(airportName).")
} else {
    print("That airport is not in the airports dictionary.")
}
// That airport is not in the airports dictionary.

ディクショナリから要素(キーバリューペア)を削除する場合、removeValue(forKey:)メソッドを使うこともできます。このメソッドはディクショナリの中に指定したキーバリューペアが存在する場合その要素を削除し、削除した値を返します。指定したキーバリューペアが存在しない場合nilを返します。

var airports = ["YYZ": "Toronto Pearson", "DUB": "Dublin"]
if let removedValue = airports.removeValue(forKey: "DUB") {
    print("The removed airport's name is \(removedValue).")
} else {
    print("The airports dictionary does not contain a value for DUB.")
}
// Prints "The removed airport's name is Dublin."

ディクショナリの要素のイテレート

ディレクトリのキーバリューペアはfor-inループで走査できます。ディクショナリ内のそれぞれの要素は(key,value)タプルとして返されます。そしてfor-in文内で一時的な変数あるいは定数としてタプルのメンバを分解できます。

var airports = ["YYZ": "Toronto Pearson", "DUB": "Dublin"]

for(airportCode,airportName)in airports{
    print("\(airportCode):\(airportName)")
}
//DUB:Dublin
//YYZ:Toronto Pearson

ディクショナリのキーの集合、あるいは値の集合を走査するのに、ディクショナリのkeysプロパティとvaluesプロパティへアクセスする方法もあります。

var airports = ["YYZ": "Toronto Pearson", "DUB": "Dublin"]

for airportCode in airports.keys{
    print("Airport code: \(airportCode)")
}
for airportName in airports.values{
    print("Airport name: \(airportName)")
}
//Airport code: YYZ
//Airport code: DUB
//Airport name: Toronto Pearson
//Airport name: Dublin
print(airports.keys)
print(type(of:airports.keys))
print(airports.values)
print(type(of:airports.values))
//["DUB", "YYZ"]
//Keys
//["Dublin", "Toronto Pearson"]
//Values

print()でairports.keys,airports.valuesを表示してみると、それぞれキーを要素にもつ配列、値を要素に持つ配列のように見えますが、厳密には配列ではなくそれぞれKeys型,Values型という構造体が用意されているんですね。

型を調べたい時はtype(of:)関数です。

配列とは型が違いますので、このまま配列としては扱えない。配列として扱いたい場合は、それぞれ配列へ型変換する必要があります。

ディクショナリのキーの集合、値の集合をArrayインスタンスとしてAPIで扱いたい場合は、keys,valuesプロパティを配列に型変換(型キャスト)しましょう。

let airportCodes = [String](airports.keys)
// airportCodes is ["LHR", "YYZ"]

let airportNames = [String](airports.values)
// airportNames is ["London Heathrow", "Toronto Pearson"]

Swiftのディクショナリ型は順番を定義されていません。キー・バリューを並べ替えたい場合、keys,valuesプロパティのsorted()メソッドを使いましょう。

var airports = ["YYZ": "Toronto Pearson", "DUB": "Dublin","NRT":"Narita","OIT":"Ooita","HND":"Haneda"]

var k=airports.keys
var v=airports.values

print(k.sorted())
print(v.sorted())
//↓並べ替えられている
//["DUB", "HND", "NRT", "OIT", "YYZ"]
//["Dublin", "Haneda", "Narita", "Ooita", "Toronto Pearson"]

 

 

 

 

 

参考

https://docs.swift.org/swift-book/LanguageGuide/CollectionTypes.html

コメントを残す

メールアドレスが公開されることはありません。