Swiftで学ぶDictionaryの使い方!15選の具体例でマスター

Swift言語を用いたDictionaryの詳細な解説イメージSwift
この記事は約19分で読めます。

 

【サイト内のコードはご自由に個人利用・商用利用いただけます】

この記事では、プログラムの基礎知識を前提に話を進めています。

説明のためのコードや、サンプルコードもありますので、もちろん初心者でも理解できるように表現してあります。

基本的な知識があればカスタムコードを使って機能追加、目的を達成できるように作ってあります。

※この記事は、一般的にプロフェッショナルの指標とされる『実務経験10,000時間以上』を凌駕する現役のプログラマチームによって監修されています。

サイト内のコードを共有する場合は、参照元として引用して下さいますと幸いです

※Japanシーモアは、常に解説内容のわかりやすさや記事の品質に注力しております。不具合、分かりにくい説明や不適切な表現、動かないコードなど気になることがございましたら、記事の品質向上の為にお問い合わせフォームにてご共有いただけますと幸いです。
(送信された情報は、プライバシーポリシーのもと、厳正に取扱い、処分させていただきます。)

はじめに

この記事を読めば、SwiftでのDictionaryの使い方を完璧にマスターすることができるようになります。

SwiftはAppleが開発した高性能で安全なプログラミング言語で、iOSやMacのアプリ開発に使用されています。

そして、DictionaryはSwiftの中でも非常に便利で多用されるデータ構造の一つです。

そのDictionaryをしっかりと理解し、効率よく使いこなすための基本から応用、さらには注意点までを、具体的なサンプルコードとともに解説していきます。

●SwiftとDictionaryの基本

Swiftは強力な言語機能と簡潔な文法を持つ言語として、多くの開発者から愛されています。

その中でも、Dictionaryはキーと値のペアでデータを管理するためのコレクション型として、非常に役立ちます。

○Swiftとは?

SwiftはAppleによって開発されたプログラミング言語です。

Objective-Cの後継として登場し、iOS、macOS、watchOS、tvOSの開発に広く用いられています。

その特徴は、読みやすく、安全性に配慮された設計や、高速な実行速度などが挙げられます。

○Dictionaryの特徴

Dictionaryは、キーと値のペアの集合を管理するためのコレクションです。

SwiftのDictionaryは、任意の型のキーと値を持つことができ、高速にデータの検索や更新が行えるのが特徴です。

このコードでは、String型のキーとInt型の値を持つDictionaryを作成しています。

この例では、”apple”というキーに対して、5という値が割り当てられています。

var fruits: [String: Int] = ["apple": 5, "banana": 3]
print(fruits["apple"]) // 5と表示されます。

このように、Dictionaryを使うことで、キーを指定して瞬時に関連する値を取り出すことができます。

●SwiftでのDictionaryの使い方

SwiftにおけるDictionaryは、キーと値のペアを保持する非常に強力なデータ構造です。

それぞれのキーはユニークであり、特定のキーに関連づけられた値を迅速に取得することができます。

ここでは、SwiftでのDictionaryの基本的な使い方をサンプルコードとともに見ていきます。

○サンプルコード1:基本的なDictionaryの作成

Dictionaryの基本的な作成は非常にシンプルです。

このコードでは、String型のキーとInt型の値を持つDictionaryを作成しています。

この例では、”apple”というキーに対して5という値、”banana”というキーに対して3という値を持っています。

var fruits: [String: Int] = ["apple": 5, "banana": 3]

このDictionaryを使用して、”apple”の値を取得すると、5が返ってきます。

print(fruits["apple"]) 
// 出力結果は5となります。

○サンプルコード2:キーを用いた値の取得

Dictionaryから値を取得する際には、キーを指定します。

このコードでは、先ほど作成したfruitsというDictionaryから”banana”の値を取得しています。

if let bananaCount = fruits["banana"] {
    print("バナナの数は\(bananaCount)です。")
} else {
    print("バナナはDictionaryに存在しません。")
}
// 出力結果は「バナナの数は3です。」と表示されます。

注意すべき点は、Dictionaryから値を取得すると、その値はオプショナル型として返されることです。

これは、指定したキーがDictionaryに存在しない場合を考慮した仕様です。

そのため、if letやguard letを用いてアンラップする必要があります。

○サンプルコード3:Dictionaryの更新と追加

Dictionaryに新しい要素を追加する、または既存の要素を更新するには、非常に直感的な方法があります。

このコードでは、先ほどのfruits Dictionaryに新しい要素を追加し、また、”apple”の値を更新しています。

fruits["orange"] = 7
fruits["apple"] = 8

このようにして、”orange”というキーに7という値を追加し、”apple”というキーの値を8に更新することができます。

print(fruits) 
// 出力結果は["apple": 8, "banana": 3, "orange": 7] となります。

キーが既にDictionaryに存在する場合は、そのキーの値が更新されます。

存在しない場合は、新しいキーと値のペアが追加されます。

○サンプルコード4:要素の削除

Dictionaryから要素を削除するには、特定のキーの値をnilに設定する方法があります。

このコードでは、fruits Dictionaryから”banana”というキーとその値を削除しています。

fruits["banana"] = nil

この操作を行うと、”banana”というキーとそれに関連づけられた値がDictionaryから削除されます。

print(fruits) 
// 出力結果は["apple": 8, "orange": 7] となり、"banana"が削除されていることが確認できます。

○サンプルコード5:Dictionaryの結合

Swiftでは、二つのDictionaryを結合することもできます。

このコードでは、二つの異なるfruitsとvegetablesというDictionaryを結合しています。

let vegetables: [String: Int] = ["carrot": 4, "potato": 10]
for (key, value) in vegetables {
    fruits[key] = value
}

この例では、fruits Dictionaryにvegetables Dictionaryの要素が追加されます。

print(fruits) 
// 出力結果は["apple": 8, "orange": 7, "carrot": 4, "potato": 10] となります。

●Dictionaryの応用例

SwiftのDictionaryには、基本的な操作だけでなく、さまざまな応用的な操作も可能です。

これにより、より柔軟で強力なデータ操作が実現します。

ここでは、そのような応用例としてよく利用される操作をサンプルコードとともに解説します。

○サンプルコード6:Dictionaryを用いたデータフィルタリング

データをフィルタリングすることは、アプリケーション開発で頻繁に行われる操作です。

Dictionaryでは、特定の条件に一致するキーや値だけを取り出すことができます。

このコードでは、fruits Dictionaryから価格が5より大きいものだけを取り出しています。

let fruits = ["apple": 3, "banana": 6, "orange": 8, "grape": 4]
let filteredFruits = fruits.filter { $1 > 5 }

このコードでは、fruitsの中で、値が5より大きいものだけを新しいDictionaryとして取得しています。

print(filteredFruits) 
// 出力結果は["banana": 6, "orange": 8] となります。

○サンプルコード7:キーの配列と値の配列を別々に取得

Dictionaryのキーや値だけを配列として取得することも可能です。

このコードでは、fruits Dictionaryのキーと値をそれぞれの配列として取得しています。

let keysArray = [String](fruits.keys)
let valuesArray = [Int](fruits.values)

これにより、キーだけの配列や、値だけの配列を簡単に取得することができます。

print(keysArray) 
// 出力結果は["apple", "banana", "orange", "grape"] となります。
print(valuesArray) 
// 出力結果は[3, 6, 8, 4] となります。

○サンプルコード8:Dictionaryの値を昇順・降順でソート

SwiftのDictionaryでは、キーや値に基づいて要素をソートすることができます。

このコードでは、fruits Dictionaryの価格を基に昇順・降順でソートする方法を紹介します。

まず、価格を昇順でソートします。

let fruits = ["apple": 3, "banana": 6, "orange": 8, "grape": 4]
let ascendingSortedFruits = fruits.sorted { $0.value < $1.value }

このコードでは、sortedメソッドを使用して、Dictionaryの値が小さいものから大きいものへと昇順にソートしています。

次に、価格を降順でソートする方法です。

let descendingSortedFruits = fruits.sorted { $0.value > $1.value }

このコードでは、sortedメソッド内のクロージャを使って、大きい価格のフルーツから小さいものへと降順にソートしています。

上記のソートを実行すると、次のような結果が得られます。

print(ascendingSortedFruits) 
// 出力結果は [("apple", 3), ("grape", 4), ("banana", 6), ("orange", 8)] となります。

print(descendingSortedFruits) 
// 出力結果は [("orange", 8), ("banana", 6), ("grape", 4), ("apple", 3)] となります。

○サンプルコード9:ネストされたDictionaryの取り扱い

Dictionaryの中に別のDictionaryが入っている、いわゆるネストされたDictionaryも、Swiftでは簡単に取り扱うことができます。

このコードでは、ネストされたDictionaryの価格情報を取り出す方法を解説します。

let nestedFruits = ["apple": ["price": 3, "color": "red"], "banana": ["price": 6, "color": "yellow"]]
let applePrice = nestedFruits["apple"]?["price"]

このコードでは、nestedFruitsというネストされたDictionaryから、”apple”の価格情報を取り出しています。

取り出した結果は次のようになります。

print(applePrice) 
// 出力結果は Optional(3) となります。

○サンプルコード10:Dictionaryを使った繰り返し処理

SwiftのDictionaryでは、for-inループを使用して、キーと値を繰り返し処理することができます。

このコードでは、fruits Dictionaryの各要素を繰り返し処理して、キーと値を出力する方法を表しています。

for (fruit, price) in fruits {
    print("\(fruit)の価格は\(price)です。")
}

このコードを実行すると、次のような結果が得られます。

// 出力結果は
// appleの価格は3です。
// bananaの価格は6です。
// orangeの価格は8です。
// grapeの価格は4です。

こうした繰り返し処理を利用することで、Dictionaryの要素を効率的に処理することができます。

●注意点と対処法

SwiftでDictionaryを使う際には、様々な注意点や、それに対する対処法が存在します。

ここでは、特に初心者から中級者に向けて、よく出会うであろう注意点とそれぞれの対処法を詳細に解説します。

○Dictionaryのメモリ管理と性能上の注意点

SwiftのDictionaryは非常に便利で高速なデータ構造ですが、大量のデータを格納すると、メモリ消費が増加し、アプリケーションのパフォーマンスに影響を及ぼす可能性があります。

また、キーのハッシュ計算に時間がかかると、特に大きなDictionaryでの検索速度が低下することも考えられます。

このコードでは、大量のデータを持つDictionaryの作成とアクセスの速度を計測しています。

import Foundation

var largeDictionary = [Int: Int]()
let startTime = CFAbsoluteTimeGetCurrent()

for i in 0..<100000 {
    largeDictionary[i] = i
}

let endTime = CFAbsoluteTimeGetCurrent()
print("データの挿入にかかった時間: \(endTime - startTime)秒")

この例では、10万の要素を持つDictionaryを作成し、その作成にかかった時間を計測しています。

次に、ランダムなキーに対するアクセスの速度を計測します。

let randomKey = Int(arc4random_uniform(100000))
let accessStartTime = CFAbsoluteTimeGetCurrent()
let _ = largeDictionary[randomKey]
let accessEndTime = CFAbsoluteTimeGetCurrent()
print("ランダムなキーのアクセスにかかった時間: \(accessEndTime - accessStartTime)秒")

このコードでは、ランダムなキーに対してDictionaryから値を取得し、そのアクセスにかかった時間を計測しています。

上記のコードを実行すると、挿入やアクセスにかかった時間が出力され、それによってDictionaryの性能を確認することができます。

○型の異なるキーや値を持つDictionaryの取り扱い

Swiftは型安全な言語であるため、一つのDictionary内に異なる型のキーや値を混在させることは基本的にはできません。

しかし、Any型を利用することで、異なる型を格納することも可能です。

このコードでは、異なる型のキーや値を持つDictionaryの作成方法を表しています。

var mixedDictionary: [AnyHashable: Any] = [
    "name": "Taro",
    "age": 25,
    100: "hundred"
]

このコードでは、String型のキー、Int型のキー、String型の値、Int型の値を持つDictionaryを作成しています。

しかし、Any型を使用することで型の情報が失われるため、値を取り出す際にはダウンキャストが必要となります。

if let name = mixedDictionary["name"] as? String {
    print(name)  // 出力結果は "Taro" となります。
}

この例では、”name”キーに関連付けられた値をStringとして取り出しています。

●カスタマイズ方法

SwiftでのDictionaryの利用法をマスターした後は、更にDictionaryをカスタマイズして、さらに便利に使う方法を理解していきましょう。

ここでは、カスタムキーの設定や拡張機能を用いたカスタマイズ方法を詳しく解説します。

○サンプルコード11:カスタムキーを持つDictionaryの作成

通常のDictionaryでは、StringやIntなどの基本的な型をキーとして使用しますが、Swiftではカスタム型をキーとして使用することも可能です。

ただし、その型がHashableプロトコルに準拠している必要があります。

このコードでは、User型をキーとして持つDictionaryの作成方法を表しています。

struct User: Hashable {
    var id: Int
    var name: String
}

var userScores: [User: Int] = [
    User(id: 1, name: "Taro"): 90,
    User(id: 2, name: "Jiro"): 85
]

この例では、User構造体を定義し、それをキーとしてスコアを格納するDictionaryを作成しています。

○サンプルコード12:拡張機能を用いたDictionaryのカスタマイズ

Swiftの拡張機能を用いることで、Dictionaryに新しい機能を追加することができます。こ

れにより、より柔軟な操作や独自の処理をDictionaryに組み込むことが可能となります。

このコードでは、Dictionaryに平均値を取得する拡張機能を追加しています。

extension Dictionary where Value == Int {
    func average() -> Double {
        let total = self.values.reduce(0, +)
        return Double(total) / Double(self.count)
    }
}

let scores = ["Taro": 90, "Jiro": 85, "Saburo": 80]
let avgScore = scores.average()
print(avgScore)  // 出力結果は 85.0 です。

この例では、Int型の値を持つDictionaryに対して、その平均値を取得するaverageメソッドを追加しています。

そして、実際にこの新しいメソッドを使用して、スコアの平均値を計算しています。

○サンプルコード13:クロージャを利用した処理のカスタマイズ

クロージャはSwiftで非常に強力なツールとして知られています。

クロージャを使用することで、関数の中でコードのブロックをキャプチャして、後でそのコードを実行することができます。

Dictionaryでもこのクロージャを利用して、独自のカスタマイズ処理を実装することが可能です。

このコードでは、Dictionaryの各要素に対して特定の処理を行い、その結果を新しいDictionaryとして返す方法を表しています。

let numbers: [String: Int] = ["one": 1, "two": 2, "three": 3]

let squaredNumbers = numbers.mapValues { (value) -> Int in
    return value * value
}

print(squaredNumbers)  // 出力内容は ["one": 1, "two": 4, "three": 9] です。

この例では、元のnumbersというDictionaryの各値を二乗して、新しいsquaredNumbersというDictionaryを生成しています。

ここで使用されているmapValuesメソッドは、Dictionaryの各値に対してクロージャ内の処理を適用し、その結果を新しいDictionaryとして返します。

○サンプルコード14:Dictionaryの変更監視とレスポンス

Swiftでは、プロパティの変更を監視するためのdidSetというプロパティオブザーバーが提供されています。

このオブザーバーを利用して、Dictionaryの変更を監視し、変更時に特定の処理を実行することができます。

このコードでは、Dictionaryが変更されたときに、その変更内容をコンソールに出力する方法を表しています。

var users: [Int: String] = [1: "Taro", 2: "Jiro"] {
    didSet(oldValue) {
        for (key, value) in users {
            if oldValue[key] != value {
                print("ID \(key)のユーザー名が\(oldValue[key] ?? "nil")から\(value)に変更されました。")
            }
        }
    }
}

users[2] = "Saburo"  // 出力内容は "ID 2のユーザー名がJiroからSaburoに変更されました。" です。

この例では、usersというDictionaryの内容が変更されるたびに、その変更内容をコンソールに出力します。

didSet内で古いDictionaryの内容と新しい内容を比較し、変更があったキーとその内容を出力しています。

○サンプルコード15:Codableを利用したJSONの変換

SwiftでのJSONの処理は、Codableプロトコルを利用することで非常にシンプルになります。

このプロトコルを利用して、JSON形式の文字列とDictionaryとの間の変換を行う方法を見ていきましょう。

このコードでは、JSON形式の文字列をSwiftのDictionaryに変換し、その逆の変換も行う方法を表しています。

import Foundation

let jsonString = """
{
    "name": "Taro",
    "age": 25
}
"""

if let jsonData = jsonString.data(using: .utf8) {
    let decoder = JSONDecoder()
    if let userDict = try? decoder.decode([String: AnyCodable].self, from: jsonData) {
        print(userDict)  // 出力内容は ["name": "Taro", "age": 25] です。

        let encoder = JSONEncoder()
        if let newData = try? encoder.encode(userDict), let newString = String(data: newData, encoding: .utf8) {
            print(newString)  // 出力内容は上記のJSON形式の文字列と同じです。
        }
    }
}

この例では、まず与えられたJSON形式の文字列をSwiftのDictionaryに変換しています。

その後、そのDictionaryを再度JSON形式の文字列に変換しています。

まとめ

Swift言語を使用してDictionaryの取り扱いを学ぶことは、データの構造や操作の基本を習得する上で非常に価値があります。

この記事を通じて、Dictionaryの基本的な操作から応用的な使い方、さらにはカスタマイズ方法まで、多岐にわたる内容を詳細に学ぶことができたかと思います。

初心者から中級者までの読者の皆様が、実際の開発シーンでのDictionaryの活用や問題解決にこの記事の内容を活かしていただければ幸いです。

特に、クロージャの利用やCodableを使ったJSONの変換などは、現代のアプリケーション開発において頻繁に使用されるテクニックです。

プログラミング学習は実践を通じての理解が鍵です。

今回学んだ内容をぜひ自分の手を動かしながら実際にコードを書いてみることをおすすめします。