見出し画像

今でしょ!Swift - コレクション型(Set,辞書)

セットは、同じ型の値を、決まった順序と値の重複なしでひとまとまりにすることができます。値の順序が重要でない場合や、値に重複がないことを保証したい場合に、配列の変わりにセットを使用することができます。

基本的には配列と同じようにつくことができます。

セット型のハッシュ値

セットに保存する型はハッシュ化が可能でなければなりません。つまり、その型はハッシュ値を計算する方法をセットに知らせる必要があります。ハッシュ値は、Int 型で、等価比較が可能な全てのオブジェクトで、例えば a == b の場合、a のハッシュ値は b のハッシュ値と等しくなります。

Swift の基本的な型(String、Int、Double、Bool など)は、デフォルトでハッシュ化が可能で、セットや辞書のキーに使用することができます。関連値を持たない列挙型のケース(Enumerations(列挙型))もデフォルトでハッシュ化が可能です。

空のセットの作成と初期化

var letters = Set<Character>()
print("letters は \(letters.count) 個の要素を持つ Set<Character> 型です。")
// letters は 0 個の要素を持つ Set<Character> 型です。

他の方法

letters.insert("a")
// letters は Character 型の値を 1 つ含んでいます
letters = []
// letters は空のセットですが、 型は Set<Character> のままです


簡略記法として、1 つ以上の値を配列リテラルを使用してセットを初期化することもできます。

下記の例は、favoriteGenres という String の値を保持するセットを作成しています。

var favoriteGenres: Set<String> = ["Rock", "Classical", "Hip hop"]
// favoriteGenres は 3 つ の初期値で初期化されている

favoriteGenres の初期化は下記のようにより簡単に書くことができます

var favoriteGenres: Set = ["Rock", "Classical", "Hip hop"]

配列の値は全て同じ型なので、favoriteGenres 変数は Set<String> が正しい型だと推論できます。

セットへのアクセスと変更

セットも配列と同じように値にアクセスできます。

カウント

print("私には \(favoriteGenres.count) 個の好きな音楽ジャンルがあります。")
// 私には 3 個の好きな音楽ジャンルがあります。

セットに新しいアイテムを追加

favoriteGenres.insert("Jazz")
// favoriteGenres 4 つのアイテムを含んでいます

セットからアイテムを削除
セットにアイテムが存在した場合は削除し、削除したアイテムを返します。もし存在しなけば nil を返します。他の方法として、全アイテムを削除するには removeAll() を使います。

if let removedGenre = favoriteGenres.remove("Rock") {
    print("\(removedGenre)? もういいです。")
} else {
    print("そのジャンルはあんまり気にしたことがないです。")
}
// Rock? もういいです。

特定のアイテムが含まれているかどうかを調べる方法

if favoriteGenres.contains("Funk") {
    print("James BrownのGet On The Good Footは最高です!")
} else {
    print("ちょっとファンキー(funky)すぎます。")
}
// ちょっとファンキー(funky)すぎます。

セットの繰り返し処理

for-in ループを使用してセットの要素を繰り返し処理する方法

for genre in favoriteGenres {
    print("\(genre)")
}
// Classical
// Jazz
// Hip hop

Swift の Set 型は決まった順序がありません。特定の順番で値を繰り返し処理したい場合、sorted() メソッドを使用することができます。

for genre in favoriteGenres.sorted() {
    print("\(genre)")
}
// Classical
// Hip hop
// Jazz

セットの操作

2 つのセットの、合成、共通の要素があるかどうか、値が全部等しいのか、いくつか等しいのか、全く違うのかの比較などを調べることができます。

基本的なセットの操作

2つ配列の値について重なりなどからリストを再構築することができます。

・intersection(_:) は、2 つのセットの共通要素を含めた新しいセットを作成します
・symmetricDifference(_:) は、どちらかのセットにあるものの、両方には含まれていない要素を含めた新しいセットを作成します
・union(_:) は、両方のセットに含まれている全ての要素を含めた新しいセットを作成します
・subtracting(_:) は、特定のセットには含まれていない要素を含めた新しいセットを作成します

let oddDigits: Set = [1, 3, 5, 7, 9]
let evenDigits: Set = [0, 2, 4, 6, 8]
let singleDigitPrimeNumbers: Set = [2, 3, 5, 7]

oddDigits.union(evenDigits).sorted()
// [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]  組み合わせて小さいものから並び替え
oddDigits.intersection(evenDigits).sorted()
// [] 重なるものはありません
oddDigits.subtracting(singleDigitPrimeNumbers).sorted()
// [1, 9] 2つのセットにはないものを表示します
oddDigits.symmetricDifference(singleDigitPrimeNumbers).sorted()
// [1, 2, 9] 重なっていない値を表示します。


セットの要素と等価性

二つのセットの値について以下の通り調べることができます。真偽値で出てきます。(true もしくはfalse)


等価演算子(==)を使用して、2 つのセットの要素が全て同じかどうかを判定できます
isSubset(of:) を使用してあるセットの要素が他のセットに全て含まれているかどうかを判定できます
isSuperset(of:) を使用してあるセットが他のセットの全ての要素を含んでいるかどうかを判定できます
isStrictSubset(of:) や isStrictSuperset(of:) は、あるセットが他のセットの上位集合か下位集合かどうかを判定できます(等しい場合は false です)
isDisjoint(with:) は 2 つのセットに共通要素が全くないかどうかを判定できます

let houseAnimals: Set = ["🐶", "🐱"]
let farmAnimals: Set = ["🐮", "🐔", "🐑", "🐶", "🐱"]
let cityAnimals: Set = ["🐦", "🐭"]

houseAnimals.isSubset(of: farmAnimals)
// true
farmAnimals.isSuperset(of: houseAnimals)
// true
farmAnimals.isDisjoint(with: cityAnimals)
// true


辞書

[apple : りんご]  ・・・  [key :  value]のように対比して作ります

のように関連させた単語を並べて便利に使えるようにしたのが辞書です。

空の辞書型の作成

配列と同じように作ることができます。

var namesOfIntegers: [Int: String] = [:]
// namesOfIntegers は空の [Int: String] 辞書

既に型情報が分かっている場合は、空の辞書リテラルを [:] と書くことができます。

namesOfIntegers[16] = "sixteen"
// namesOfIntegers は 1 つのキーバリューペアを含んでいます
namesOfIntegers = [:]
// namesOfIntegers は再び [Int: String] の空の辞書


辞書リテラルを使った辞書の作成

配列と同じような初期化もできます。

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

もっと簡単に

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


辞書へのアクセスと変更

メソッドやプロパティ、サブスクリプト構文を使って、辞書へのアクセス、変更ができます。

配列と同様に、Dictionary のアイテムの数を"count"を使って調べることができます。

print("airports 辞書には \(airports.count) 個のアイテムがあります。")
// airports 辞書には 2 個のアイテムがあります。

Bool 型の isEmpty プロパティは、count プロパティが "0 "かどうかをチェックする簡略記法です。

if airports.isEmpty {
    print("airports 辞書は空です。")
} else {
    print("airports 辞書は空ではありません。")
}
// airports 辞書は空ではありません。

サブスクリプト構文を使用して、新しいアイテムを追加することができます。新しいキーとなる値を指定して新しいバリューを代入できます。

airports["LHR"] = "London"
// airports 辞書は 3 つのアイテムを含んでいます

サブスクリプト構文を使用すると、特定のキーのバリューを変更することもできます。

airports["LHR"] = "London Heathrow"
// "LHR"の値は "London Heathrow" へ変更

別の方法として、updateValue(_:forKey:) メソッドを使用して、特定のキーのバリューの設定/更新ができます。

updateValue(_:forKey:) メソッドは、辞書のバリューの型のオプショナル値を返します。例えば辞書が String を保持している場合、このメソッドは String?(オプショナル String)を返します。このオプショナル値は更新前にバリューが存在していた場合はその値のオプショナルを返し、存在していなかった場合は nil を返します:

if let oldValue = airports.updateValue("Dublin Airport", forKey: "DUB") {
    print("DUB キーに対する更新前のバリューは \(oldValue) でした。")
}
// DUB キーに対する更新前のバリューは Dublin でした。

サブスクリプト構文を使用して特定のキーのバリューを取得することもできます。バリューの存在しないキーに対してもリクエストすることが可能で、バリューの型のオプショナル値を返します。存在しなければ nil を返します:

if let airportName = airports["DUB"] {
    print("この空港の名前は \(airportName) です。")
} else {
    print("その空港は airports 辞書にはありません。")
}
// この空港の名前は Dublin Airport です。

サブスクリプト構文を使用して、キーに nil を代入することで、キーバリューペアを削除できます:

airports["APL"] = "Apple International"
// "Apple International" APL の空港ではないので削除します
airports["APL"] = nil
// APL は辞書から削除されました

他の方法として、removeValue(forKey:) メソッドを使用してキーバリューペアを削除できます。バリューが存在すれば削除した値を返し、存在しなければ nil を返します

if let removedValue = airports.removeValue(forKey: "DUB") {
    print("削除された空港の名前は \(removedValue) です。")
} else {
    print("airports 辞書には DUB キーに対する値がありません。")
}
// 削除された空港の名前は Dublin Airport です。

辞書の繰り返し処理

for-in ループを使用して辞書のキーバリューペア全部に繰り返し処理することができます。各アイテムは (key, value) のタプルを返し、繰り返し処理の中で、このタプルを一時的な定数や変数に展開することができます。

for (airportCode, airportName) in airports {
    print("\(airportCode): \(airportName)")
}
// LHR: London Heathrow
// YYZ: Toronto Pearson

keys と values プロパティを使用して、キーとバリューそれぞれのリストを取得することもできます:

for airportCode in airports.keys {
    print("空港コード: \(airportCode)")
}
// 空港コード: LHR
// 空港コード: YYZ

for airportName in airports.values {
    print("空港名: \(airportName)")
}
// 空港名: London Heathrow
// 空港名: Toronto Pearson

辞書データをキーまたはバリューの値を取り出してそれぞれの配列にすることができます。

let airportCodes = [String](airports.keys)
// 空港コードは ["LHR", "YYZ"]

let airportNames = [String](airports.values)
// 空港名は ["London Heathrow", "Toronto Pearson"]

Dictionary 型には決まった順序がありません。特定の順番で値を繰り返し処理をしたい場合、keys か values プロパティの sorted() メソッドを使います。

いいなと思ったら応援しよう!