티스토리 뷰

집단 자료형 - 딕셔너리

(Collection Type - Dictionary)




1) 이론적 정의

 


1. Swift 에서 사용되는 집단 자료형으로는 배열(Array) , 집합(Set) , 딕셔너리(Dictionnary) 가 있다. 여기서는 딕셔너리에 대해 알아보자.




2) 딕셔너리(Dictionary)


 

 1.  자료형 내 각 요소마다 고유한 키와 그 키에 대한 값을 가지는 자료형 (Element = Unique Key + Value)


 2.  순서가 없는 집단 자료형 (Unordered Collection)




* Example 1-1. 딕셔너리의 선언과 초기화



1) var dictFromLiteral = ["key 1": "value 1", "key 2": "value 2"]


  --> 딕셔너리의 선언 예시.


2) var dictFro mLiteral = [1: "value 1", 2: "value 2"]


  --> 'Key' 부분에 문자열 뿐만 아니라 정수도 사용할 수 있다. 그러나, 굳이 정수를 넣을 거라면 순서대로 정수 인덱스를 가지는 배열을 사용하는게 더 좋지 않을까?


3) var dictFromLiteral = ["1": 1, "2": 2] 

 --> 물론 'Value' 부분에도 문자열이 아닌 정수도 사용이 가능하다.


  * var dictFromLiteral = [:] : 이런 식으로 선언하면 오류 발생.




* Example 2. 딕셔너리 타입(Dictionary Type)



let words1: Dictionary<String, String> = ["A": "Apple", "B": "Banana", "C": "City"]


  --> 키와 값이 모두 문자열인 딕셔너리를 선언하는 타입 선언 방법 1. 길어서 애용되지는 않음. 아래 방법 2, 3이 많이 쓰인다. 


let words2: [String: String] = ["A": "Apple", "B": "Banana", "C": "City"]


 -->  위의 타입 선언이 길다면 줄여서 이렇게도 쓸 수 있는 딕셔너리 타입 선언 방법 2


let words3 = ["A": "Apple", "B": "Banana", "C": "City"]


 --> 앞서 배운 타입 추론을 통해 컴파일러가 이 딕셔너리의 타입을 추론하는 딕셔너리 타입 선언 방법 3




* Example 3. 요소의 개수(Number of elements)



var words = ["A": "Apple", "B": "Banana", "C": "City"]


  --> 3개의 key 와 3개의 value를 가진 딕셔너리 타입의 변수 words.


let countOfWords = words.count


  -->  배열의 개수를 확인할 때와 마찬가지로 '.count' 를 사용하여 딕셔너리의 요소의 개수를 확인할 수 있다.


if !words.isEmpty {                                                <-- words 앞의 ! 기호는 not 을 의미한다. 결국. 딕셔너리의 배열이 비어있지 않으면 True 가 된다.

  print("\(countOfWords) element(s)")

} else {

  print("empty dictionary")

}


  --> '.count' 이외에도 우리는 배열의 요소가 비어있는지 확인할 수 있는 메소드 '.isEmpty' 를 활용해 딕셔너리 내 요소의 개수를 확인할 수 있다. 

        위의 if 문에서는 앞서 선언한 딕셔너리가 비어있지 않고, 3개의 요소를 가지고 있으므로 3 element(s) 가 출력된다.




* Example 4. 딕셔너리 내 요소 찾기 (Retrieve an element)




var words = ["A": "Apple", "B": "Banana", "C": "City"]


print(words["A"])                // Optional("Apple")


  --> 딕셔너리로 선언된 words 에 있는 키 값 "A" 를 프린트 했는데 우리가 생각하는 결과인 "Apple" 이 아닌 Optional("Apple") 이 출력되었다. 무슨 일일까?

       지금 위의 예시는 우리가 한 눈에 값이 있는 것을 확인할 수 있는 상태이다. 그러나 프로그램이 키를 호출 했을 때, 값이 비어있을 가능성이 있다. 그러면

       오류를 발생시키기 때문에, 이것을 안전하게 처리하기 위해서 스위프트에서는 '옵셔널(Optional)' 이라는 개념을 사용한다.


print(words["Q"])                // Nil


  --> 위에서 배운 옵셔널을 잘 기억해보자. 옵셔널은 해당하는 값이 존재하지 않을 때 'Nil' 이라는 값을 반환한다. 

        위의 words 변수에서 키 값 "Q' 는 존재하지 않는다. 그래서 옵셔널으로 반환하지 못하고 값이 존재하지 않는다는 'Nil' 을 반환하게 된다.



Q. 그렇다면 저 옵셔널을 없애려면 어떻게 하면 될까요?


A. '옵셔널 바인딩(Optional Binding)' 을 활용하여 안전하게 옵셔널을 해제하면 됩니다. 



if let aValue = words["A"] {

  print(aValue)                                <-- "A" 벨류 값의 존재 여부는 true 가 되어 안전하게 옵셔널을 해제할 수 있게 되었습니다.

} else {

  print("Not found")

}


if let zValue = words["Z"] {

  print(zValue)

} else {

  print("Not found")                         <-- "Z" 벨류 값의 존재 여부는 false 가 되어 옵셔널을 해제하지 못하고 "Not found" 부분을 출력합니다.

}



딕셔너리 내부의 요소에는 순서가 없다! (Unordered)



print(words.keys)                // ["C", "B", "A"]

print(words.values)             // ["City", "Banana", "Apple"]



우리가 선언한 순서대로 나오지 않는다 !





* Example 5. 딕셔너리 내부에 새로운 요소 추가하기 (Add a new element)



words = ["A": "A"]

  

  --> 기존 위에서 살펴본 words는 잊고, 다시 새롭게 요소를 추가한다고 생각하자. 문자열 키 값 A 와 문자열 벨류 값 A 를 추가하였다. 


words["A"]


  --> 벨류 값은 키 값을 통해 접근할 수 있다. A 키 값에 접근 했으니 결과는 벨류 값 A를 나타낸다.


words["A"] = "Apple"


  --> 키 값은 고유하기 때문에 Apple 이라는 벨류 값을 가진 키 값 A 는 기존의 words 딕셔너리 내부의 새로운 요소로 들어갈 수 없다(이미 키 A가 존재하니까)

       대신 값의 수정이 발생한다. 


words      // ["A": "A"]  에서  ["A": "Apple"] 로 수정이 되었다.


  --> 아래는 위와 동일하게 값을 넣고 수정하는 과정이다. 어떻게 딕셔너리 내부가 변할 지 직접 해보자.


words["B"] = "Banana"

words


words["B"] = "Blue"

words






* Example 6. 딕셔너리 내부에 존재하는 요소를 변경하기 (Change an existing element)



앞서 키와 값을 추가하는 방법을 있지만 메소드를 사용해서 키를 추가할 수도 있다.

.updateValue("Value", forKey: "Key") 를 사용한다.

기존의 키가 존재하는 요소는 새롭게 변경하고, 기존에 없는 키의 요소는 딕셔너리 내부에 새롭게 추가하는 역할도 한다.

쉽게, 있으면 변경하고 없으면 추가한다 보면 된다. 



앞서, 옵셔널 바인딩때 사용했던 구문과 유사한 내용입니다. 


words = [:]


   --> 빈 딕셔너리 words 가 있습니다.


if let oldValue = words.updateValue("Apple", forKey: "A") {      <-- 데이터를 참조하거나 저장하는데 사용할 키 값 A 와 저장할 데이터 벨류 값 Apple을 넣고자 합니다.

          기존의 키가 존재하면 (1) 부분이 출력되고 그렇지 않으면 (2) 부분이 출력됩니다.

  print("\(oldValue) => \(words["A"]!)")                                       <-- (1)

} else {

  print("+ \(words["A"]!)")                                                           <-- (2)

}



기존의 존재하지 않았던 Key 이기 때문에 (2) 부분을 출력합니다. + Apple 이 출력되겠네요.


words         <--  ["A": "Apple"]


이 메소드에는 좀 특이한 점이 있는데, 기존의 존재하던 값을 수정하면 수정하기 이전의 값이 결과값으로 반환된다.

그 말은 새로운 키와 값의 경우에는 이전의 값이 존재하지 않는다. 값이 존재하지 않는다는 것을 Swift 에서는 'nil' 이라고 하는데 바로 이것이 반환된다.



위의 예와 유사한 예이다. 다른 점은 위와 다르게 (1) 부분이 출력된다는 것이다.



if let oldValue = words.updateValue("Apricot", forKey: "A") {

  print("\(oldValue) => \(words["A"]!)")                                         <-- (1)

} else {

  print("+ \(words["A"]!)")                                                             <-- (2)

}



자, 그럼 (1) 부분의 출력된 결과를 살펴보자.


"Apple => Apricot"      


원래대로라면 Apricot 를 업데이트 해준 부분이 oldValue에 들어갔으니까 Apricot => Apricot 가 나와야 하는데,

이 메소드의 특성 상, 수정하기 이전의 값을 반환한다. 그래서 Apple => Apricot 가 출력된 것이다.           



words.updateValue("Banana", forKey: "B") 의 반환값은 무엇일까?


기존의 값이 없던 키인 B 이니까 nil 을 반환하게 된다. 




* Example 7. 딕셔너리 내부 요소 제거(Remove an element)




1) 키 값에 nil 을 할당하여 제거할 수 있다.



words = ["A": "Apple", "B": "Banana", "C": "City", "Z": "Zoo"]


words["Z"] = "ZZZ"


  --> Z 키의 벨류 값 벼경


words["Z"] = nil


  --> Z 키의 벨류 값에 nil 을 할당


words


  --> Z 키의 값 제거. 결과 :  ["B": "Banana", "A": "Apple", "C": "City"]



2) .updateValue("value", forKey: "Key") 와 반대로, .removeValue(forKey: "Key") 를 사용하여 제거할 수 있다.

     업데이트 메소드는 기존의 값을 결과로 반환하지만, 리무브 메소드는 실행의 결과로 삭제된 아이템의 값을 반환한다. 



words = ["A": "Apple", "B": "Banana", "C": "City""D": "Drama", "E": "Earth", "F": "Fuel"]


if let removedValue = words.removeValue(forKey: "D") {

  print("\(removedValue) removed!")                                          <-- removedValue == Drama / 결과 : Drama removed!

}


words                          <-- ["B": "Banana", "A": "Apple", "F": "Fuel", "C": "City", "E": "Earth"]



.removeAll() 메소드를 사용하면 묻지도 따지지도 않고 다 삭제를 해버린다.



words.removeAll()       <-- [:]





지금까지 딕셔너리(Dictionary)에 대해서 알아보았습니다. 틀린 부분이 있으면 댓글로 지적해주시면 감사드리겠습니다.


Made by Inswag's Swift in FastCampus 7th iOS Development School

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함