콜렉션 타입 (Collection Types) - 딕셔너리 (Dictionaries)

00yhsp·2024년 4월 4일

딕셔너리 (dictionary) 는 순서와 상관없이 콜렉션에 같은 타입의 키 (key)와 같은 타입의 값 (value)를 저장한다.
각 값은 딕셔너리 내부에서 값에 대한 식별자로 동작하는 유니크한 키 와 조합됩니다. 배열의 아이템과 다르게 딕셔너리의 아이템은 특정 순서를 가지고 있지 않습니다. 특정 단어를 찾기위해 사전을 찾는 방법과 같이 식별자를 기준을 값을 찾을 때 딕셔너리를 사용합니다.

Note:
Swift의 Dictionary 타입은 Foundation의 NSDictionary 클래스와 연결된다.

딕셔너리 타입 짧은 구문 (Dictionary Type Shorthand Syntax)

Swift 딕셔너리의 타입은 Dictionary<Key, Value> 로 적으며 Key 는 딕셔너리 키로 사용되는 값의 타입이고 Value 는 딕셔너리에 저장될 값의 타입이다.

Note:
딕셔너리 Key 타입은 집합의 값 타입과 같이 반드시 Hashable 프로토콜을 준수해야 한다.

[Key: Value] 와 같이 짧은 형식으로 딕셔너리 타입을 작성할 수도 있다.

빈 딕셔너리 생성 (Creating an Empty Dictionary)

배열 처럼 초기화 구문을 사용하여 타입을 포함한 빈 Dictionary 를 생성할 수 있다.

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

이 예제에서 정수 값에 사람이 읽을 수 있는 이름을 저장하는 [Int: String] 타입의 빈 딕셔너리를 생성한다.
키는 Int 타입이고 값은 String 타입이다.

컨텍스트가 이미 타입 정보를 제공한다면 [:] (대괄호 안에 콜론을 포함해야 한다)와 같이 작성하여 빈 딕셔너리 리터럴로 빈 딕셔너리를 생성할 수 있다.

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

딕셔너리 리터럴로 딕셔너리 생성 (Creating a Dictionary with a Dictionary Literal)

앞서 배열 리터럴과 비슷한 구문을 가진 딕셔너리 리터럴 (dictionary literal) 로 딕셔너리를 초기화 할 수 있다.
딕셔너리 리터럴은 Dictionary 콜렉션으로 하나 이상의 키-값 쌍으로 작성하는 짧은 작성법이다.

키-값 쌍 은 키와 값의 결합이다.
딕셔너리 리터럴에서 각 키-값 쌍의 키와 값은 콜론으로 구분된다.
키-값 쌍은 콤마로 구분하고 대괄호로 둘러싸 리스트 형식으로 작성된다.

[<#key 1#>: <#value 1#>, <#key 2#>: <#value 2#>, <#key 3#>: <#value 3#>]

아래 예제는 국제 공항의 이름을 저장하는 딕셔너리를 생성한다.
딕셔너리의 키는 3글자로 된 국제 항공 운송 협회 (Air Transport Association) 코드이고 값은 공항 이름이다.

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

airports 딕셔너리는 Dictionary 키는 String 타입이고 값은 String 타입인 [String: String] 타입을 갖도록 선언된다.

airports 딕셔너리는 2개의 키-값 쌍을 포함한 딕셔너리 리터럴로 초기화된다.
첫번째 쌍은 "YYZ" 의 키와 "Toronto Pearson" 값을 가진다.
두번째 쌍은 "DUB" 의 키와 "Dublin" 값을 가진다.

딕셔너리 리터럴은 2개의 String: String 쌍을 포함한다.
키-값 타입은 airports 변수 선언 (딕셔너리는 String 키와 String 값만 가능) 타입과 동일하며 airports 딕셔너리에 2개의 초기 아이템을 포함하여 초기화 하는 것 또한 가능하다.

배열과 마찬가지로 키와 값이 일관된 타입을 갖는 딕셔너리 리터럴로 초기화하는 경우 딕셔너리 타입을 작성할 필요가 없다.
airports 의 초기화는 짧은 표현으로 작성 가능하다.

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

리터럴 안에 모든 키와 값이 각각 같은 타입이기 때문에 Swift는 airports 딕셔너리를 사용하기 위해 [String: String] 이 올바른 타입이라는 것을 추론할 수 있다.

딕셔너리 접근과 수정 (Accessing and Modifying a Dictionary)

메서드와 프로퍼티 또는 서브 스크립트 구분을 사용하여 딕셔너리에 접근과 수정이 가능하다.

배열과 마찬가지로 읽기 전용 count 프로퍼티로 Dictionary의 아이템 갯수를 확인할 수 있다.

print("The airports dictionary contains \(airports.count) items.")
// Prints "The airports dictionary contains 2 items."

count 프로퍼티가 0 과 같은지 아닌지 부울 isEmpty 프로퍼티를 이용하여 확인할 수 있다.

if airports.isEmpty {
    print("The airports dictionary is empty.")
} else {
    print("The airports dictionary is not empty.")
}
// Prints "The airports dictionary is not empty."

서브 스크립트 구문을 사용하여 딕셔너리에 새로운 아이템을 추가할 수 있다.
적절한 키의 타입을 서브 스크립트 인덱스로 사용하고 적절한 값의 타입을 할당한다.

airports["LHR"] = "London"
// the airports dictionary now contains 3 items

특정 키를 서브스크립트 구문으로 사용하여 값을 변경할 수 있다.

airports["LHR"] = "London Heathrow"
// the value for "LHR" has been changed to "London Heathrow"

서브 스크립트 외에 딕셔너리의 updateValue(:forKey:) 메소드를 사용하여 특정 키에 값을 설정하거나 업데이트 할 수 있다.
위의 서브 스크립트 예제와 같이 updateValue(
:forKey:) 메소드는 해당 키에 값이 존재하지 않으면 값을 설정 하거나 해당 키에 값이 존재하면 값을 업데이트한다.
그러나 서브 스크립트와 다르게 updateValue(_:forKey:) 메소드는 업데이트 수행 후에 이전 값을 반환한다.
이를 통해 업데이트가 발생했는지 여부를 알 수 있다.

updateValue(_:forKey:) 메소드는 딕셔너리의 값 타입의 옵셔널 값을 반환한다.
예를 들어 딕셔너리에 String 값을 저장하면 String? 타입 또는 "옵셔널 String"을 메서드는 반환한다.
이 옵셔널 값은 해당 키에 존재한 업데이트 전의 값 또는 존재한 값이 없었을 때는 nil 을 담고 있다.

if let oldValue = airports.updateValue("Dublin Airport", forKey: "DUB") {
    print("The old value for DUB was \(oldValue).")
}
// Prints "The old value for DUB was Dublin."

특정 키로 딕셔너리의 값을 가져올 때 서브 스크립트 구문을 사용할 수도 있다.
값이 없는 키로 요청이 가능하기 때문에 딕셔너리의 서브 스크립트는 딕셔너리의 값 타입의 옵셔널 값을 반환한다.
딕셔너리에 요쳥된 키의 값이 있는 경우 서브 스크립트는 그 값의 옵셔널 값을 반환한다.
반대로 서브 스크립트는 nil 을 반환한다.

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

딕셔너리의 해당 키에 nil 값을 할당하여 키-값 쌍을 서브 스크립트 구문을 사용하여 삭제할 수 있다.

airports["APL"] = "Apple International"
// "Apple International" is not the real airport for APL, so delete it
airports["APL"] = nil
// APL has now been removed from the dictionary

또한 딕셔너리에 removeValue(forKey:) 메서드를 사용하여 키-값 쌍을 삭제할 수 있다.
이 메서드는 키-값 쌍이 존재하면 삭제하고 삭제된 값을 반환하거나 값이 존재하지 않으면 nil 을 반환한다.

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 Airport."

딕셔너리 반복 (Iterating Over a Dictionary)

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("Airport code: \(airportCode)")
}
// Airport code: LHR
// Airport code: YYZ

for airportName in airports.values {
    print("Airport name: \(airportName)")
}
// Airport name: London Heathrow
// Airport name: Toronto Pearson

딕셔너리의 키 또는 값을 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의 Dictionary 타입은 정의된 순서를 가지고 있지 않다.
특정 순서로 딕셔너리의 키 또는 값을 반복하려면 keys 또는 values 프로퍼티에 sorted() 메서드를 사용해야 한다.

profile
iOS Dev

0개의 댓글