5.4.2 딕셔너리에 동적으로 아이템 추가하기
선언과 초기화까지 완료된 딕셔너리에 동적으로 아이템을 추가해봅시다. 앞에서 학습했던 capital 변수의 딕셔너리 정의 구문을 제거하고, 새롭게 선언한 다음 키와 값을 직접 대입하여 아이템을 추가해 봅시다
var newCapital = [String: String]()
newCapital["JP"] = "Tokyo"
키와 값을 직접 대입하여 아이템을 추가할 수 있습니다. 딕셔너리 변수 뒤에 []을 붙이고, 괄호 안에 키로 사용할 String을 넣어주고 대입 연산자로 String 값을 넣어주면 됩니다.
딕셔너리에서도 배열처럼 아이템의 개수가 딕셔너리의 크기를 결정합니다. 정확히는 딕셔너리에 저장된 튜플의 개수이죠. 딕셔너리에 아이템이 있는지는 isEmpty 속성을 통해 확인할 수 있으며 딕셔너리의 크기를 알려주는 count 값이 0일 때 isEmpty 속성의 값은 true로 설정됩니다.
if newCapital.isEmpty {
print("딕셔너리가 비어 있습니다")
} else {
print("딕셔너리의 크기는 현재 \(newCapital.count)입니다")
}
// 결과
딕셔너리의 크기는 현재 1입니다
이번에는 메서드를 사용해서 동적으로 값을 할당해봅시다. 딕셔너리에 값을 할당하는 데 사용되는 메서드는 updateValue(_:forKey:)입니다. 만약 기존에 저장된 키가 있으면 연결된 값을 수정하는 역할을 하고, 새로운 키가 입력되면 아이템을 추가하는 역할도 수행합니다. 특이한 점은 이 메서드를 사용하여 딕셔너리에 저장된 값을 수정하면 수정하기 이전의 값이 결과값으로 반환된다는 점입니다. 따라서 새로운 키와 값을 이 메서드를 사용하여 추가하면 기존에 저장되어 있던 값이 없으므로 nil을 반환합니다.
<딕셔너리 객체>.updateValue(<저장할 데이터>, forKey:<데이터를 참조 및 저장하는 데 사용할 Key>)
newCapital.updateValue("Seoul", forKey: "KR")
// "KR" : "Seoul" 데이터가 추가되고 nil 리턴
newCapital.updateValue("London", forKey: "EN")
// "EN" : "London" 데이터가 추가되고 nil을
newCapital.updateValue("Seoul", forKey: "KR")
// "JP" : "Sapporo" 데이터로 수정되고 "Tokyo"를 리턴함
첫 번째와 두 번째 경우는 이전에 사용된 적이 없는 키이므로 저장된 값도 없습니다. 따라서 키와 값이 새로 생성되고 이전에 저장된 것이 없다는 의미로 nil이 반환됩니다. 하지만 세 번째 경우는 이미 사용되었던 키이고, Tokyo라는 값을 갖고 있었으므로 Tokyo가 반환됩니다.
딕셔너리에 저장된 값을 제거할 때는 두 가지 방법이 있습니다. 하나는 키에 연결된 값에 직접 nil을 할당하는 방법이고 또 다른 하나는 명시적으로 removeValue(forKey:) 메서드를 사용하는 것입니다
newCapital.updateValue("Ottawa", forKey: "CA")
newCapital.updateValue("Beijing", forKey: "CN")
// 1. nil 할당
newCapital["CN"] = nil
// 2. 메서드 이용
newCapital.removeValue(forKey: "CA")
위 두 가지 방법으로 딕셔너리 내 아이템을 제거할 수 있습니다. 두 번째 방식의 경우 실행된 결과로 삭제된 아이템의 값을 반환받습니다.
if let removedValue = newCapital.removeValue(forKey: "CA") {
print("삭제된 값은 \(removedValue)입니다")
} else {
print("아무것도 삭제되지 않았습니다")
}
// 결과
삭제된 값은 Ottawa 입니다
물론 없는 키를 삭제하고자 할 때는 그 결과값도 당연히 없으므로 nil을 반환합니다. 그런데 여기서 짚고 넘어가야 할 부분이 있는데 바로 배열의 인덱스와 딕셔너리의 키에 대한 접근 차이입니다.
배열은 인덱스를 직접 참조하기 위해 참조할 인덱스가 이미 만들어져 있어야만 한다는 제약조건이 있습니다. 그렇지 않으면 잘못된 인덱스 참조에 의한 오류가 발생합니다. 하지만 딕셔너리는 키 자체가 일련의 순서를 갖고 있지 않습니다.(해시 연산에 의한 결과값 역시 연속되는 값은 아닙니다). 게다가 타입은 알 수 있을지언정 실제로 어떤 데이터가 키로 사용될지 미리 알 수 없으므로 기존에 사용된 적이 없던 새로운 키가 입력되면 이 키와 값을 저장하기 위한 튜플을 하나 만들어 저장하면 될 뿐입니다. 새로운 인덱스 공간을 확보하고 크기를 늘릴 필요 없이 초기화 되어 있기만 하면 됩니다.
딕셔너리는 없는 키를 호출했을 가능성을 생각해야 합니다. 이 경우를 처리해야 안전한 프로그래밍이 됩니다. 따라서 스위프트에서는 딕셔너리로부터 키를 호출해서 저장된 값을 불러올 때, 또는 업데이트 메서드를 실행한 결과를 반환할 때, 오류가 발생할 가능성을 염두에 둔 다음과 같은 특별한 형식으로 값을 반환합니다
Optional("Sapporo")
이 옵셔널은 6장에서 자세히 배워보겠습니다
Last updated