본문 바로가기
⌨️ Language/swift

[Swift] 콜렉션 타입

by hyebin (Helia) 2024. 3. 16.

1. Array

배열의 정의

  • swift에서 가장 일반적으로 사용되는 자료구조 중 하나
  • 동일한 유형의 값의 순서가 있는 콜렉션 타입
  • 각 요소는 인덱스를 사용해 접근 가능

배열의 선언과 초기화

  • 대괄호([]) 기호를 사용하여 빈 배열을 선언
var numbers: [Int] = []
var numbers = [Int]()
  • 대괄호([]) 안에 값을 쉼표로 구분하여 나열
var numbers = [1, 2, 3, 4, 5]
  • 배열을 초기화 할 때, 타입 어노테이션(type annotation)을 사용하여 배열의 타입 지정 가능
var numbers: [Int] = [1, 2, 3, 4, 5]
  • Swift는 타입 추론(type inference)을 지원하기 때문에, 타입을 생략할 수 있음
    • 초기값을 기반으로 배열의 타입을 추론
var numbers = [1, 2, 3, 4, 5] // numbers의 타입은 [Int]로 추론됩니다.
  • 배열에 다른 타입의 요소들을 저장하는 혼합배열 또는 Any 배열을 생성 가능
    • 가능한 모든 요소가 동일한 유형의 배열을 사용하는것이 좋음
var mixedArray = [1, "two", 3.0]

 

배열 요소 접근

  • 인덱스(index)를 사용하여 배열의 요소에 접근
  • 배열의 인덱스는 0부터 시작
var numbers = [1, 2, 3, 4, 5] 
let firstNumber = numbers[0] // 1 let secondNumber =numbers[1] // 2
  • 배열의 마지막 요소에 접근하려면 count 속성을 사용하여 배열의 길이를 가져온 후, 인덱스는 count-1로 설정
let lastNumber = numbers[numbers.count-1]

let n = [1, 2, 3]
print(n[1..<2]) //2
print(n[1...2]) //2, 3
  • 특정 인덱스를 찾기 위해서는 firstIndex(of: ) 메서드를 사용
    • 배열에 동일한 요소가 있는 경우, 더 작은 인덱스를 반환
    • optional 값으로 반환
var arr = [1,2,3,4,5]
arr.firstIndex(of: 1) //Optional(0)

 

배열에 요소 추가

  • 새로운 요소를 배열에 추가하기 위해서는,  append()  메서드를 사용
var numbers = [1, 2, 3, 4, 5] 
numbers.append(6) // 6을 배열의 마지막 요소로 추가합니다.
  • 특정 위치에 요소를 추가하기 위해서는,  insert()  메서드를 사용
    • insert를 하는 위치부터 배열을 재배치 해야 하기 때문에 오버헤드가 발생
    • 가능한 append 사용
var arr = [1, 2, 3, 4, 5]
arr.insert(10, at: 3) //10을 배열의 3번째에 추가합니다.
print(arr) //[1, 2, 3, 10, 4, 5]

 

배열의 수정

  • 배열의 요소를 수정하기 위해서는 인덱스를 사용하여 해당 요소에 접근한 후, 값을 변경
var numbers = [1, 2, 3, 4, 5] 
numbers[2] = 30 // 세 번째 요소를 30으로 변경합니다.ㄱㄷ배
  • 배열의 특정 범위의 값을 수정하고 싶을 때  replaceSubrange  를 사용하여 값을 변경 가능
var array2 = [1, 2, 3]
array2.replaceSubrange(0...2, with: [10, 20, 30])     // [10, 20, 30]
array2.replaceSubrange(0...2, with: [0])              // [0]
array2.replaceSubrange(0..<1, with: [])               // []

배열의 삭제

  • 배열의 요소를 삭제하기 위해서는,  remove()  메서드를 사용
var numbers = [1, 2, 3, 4, 5] 
numbers.remove(at: 2) // 세 번째 요소를 삭제합니다.

numbers.removeFirst() //배열의 첫 번째 요소를 삭제합니다.
numbers.removeLast()  //배열의 마지막 요소를 삭제합니다.
numbers.removeAll()   //배열의 모든 요소를 삭제합니다.
함수 이름 용도 리턴 타입
 remove(at:) 파라미터로 받은 index에 해당하는 값 삭제 삭제된 값 리턴Non-Optional Type
 removeFirst 첫 번째 요소 삭제 삭제된 값 리턴Non-Optional Type
 removeFirst(_:) 첫 번째 요소부터 파라미터로 받은 갯수 만큼 삭제 X
 removeLast  마지막 요소 삭제 삭제된 값 리턴Non-Optional Type
 popLast 마지막 요소 삭제 삭제된 값 리턴Non-Optional Type
 removeLast(_:) 마지막 요소부터 파라미터로 받은 갯수 만큼 삭제 X
 removeAll 전체 요소 삭제 X
 removeSubrange(_:) 파라미터로 받은 범위만큼 index 요소 삭제 X
 [n...m] = []
Subscript 문법으로 n ~ m까지 index 요소 삭제 X

 

배열의 기타 기능

 max() 배열의 최대값 반환
 min() 배열의 최소값 반환
 sort() 배열을 오름차순으로 정렬
 sort(by: >) 배열을 내림차순으로 정렬
 isEmpty 배열이 비어있는지 확인
 elementsEqual(arr) 다른 배열과 같은 배열인지 비교
 contains(n) 배열에 n이 존재하는지 확인
 swapAt(a, b) 인덱스 a의 요소와 인덱스 b의 요소를 변경

 

2. Dictionary

Dictionary의 정의

  • 딕셔너리는 키(Key) 와 값(Value)의 쌍으로 구성되는 순서가 없는 자료구조
  • 딕셔너리에서 key는 value를 대변하는 유일한 식별자가 됨
    • 딕셔너리 안에는 같은 이름을 가진 key가 존재하지 않음(유일성)
    • 딕셔너리 안에서 value는 유일하지 않음
  • 각 value는 key로 접근이 가능
  • 딕셔너리 내부에 존재하지 않는 key로 접근하게 되면 nil 값을 반환

Dictionary의 선언

  • 대괄호([]) 안에 key와 value의 쌍들을 넣어 초기화
/*
	var [딕셔너리 이름]:  Dictionary<키 타입, 값 타입> = Dictionary<키 타입, 값 타입>()
*/
// Dictionary 선언
var anyDictionary: Dictionary<String, Int> = [String: Int]()
    
// 동일 표현 - 리터럴 이용
var anyDictionary: Dictionary<String, Any> = Dictionary<String, Any>()
var anyDictionary: Dictionary<String, Any> = [:]
var anyDictionary: [String: Any] = Dictionary<String, Any>()
var anyDictionary: [String: Any] = [String: Any]()

// 동일 표현 - 빈 딕셔너리 생성
var anyDictionary: [String: Any] = [:]
var anyDictionary = [String: Any]()

// 초기화
var anyDictionary: [String: Int] = ["extramilejin": 28, "korea": 2021]

 

Dictionary의 value 설정

  • 딕셔너리의 value에 접근하는 가장 흔한 방법은 key를 subscript로써 사용
  • 딕셔너리에서 key에 해당하는 값이 없을 수 있기 때문에, 반환 값은 optional 인스턴스
    • subscript
    • 더보기
      더보기
      - 컬렉션, 리스트, 집합 등 특정 member elements에 간단하게 접근하는 문법
      - 괄호 안에 index를 넣어 member elements에 접근
      - 추가적인 메소드 없이 특정 값을 할당하거나 가져올 수 있음
var responseMessages = [200: "OK",
                        403: "Access forbidden",
                        404: "File not found",
                        500: "Internal server error"]

print(responseMessages[200])
// Optional("OK")
  • if let 구문을 사용하여 딕셔너리에서 key에 해당하는 값의 유무에 따라 다른 동작을 수행
let httpResponseCodes = [200, 403, 301]
for code in httpResponseCodes {
		//key에 해당하는 값 존재
    if let message = responseMessages[code] {
        print("Response \\(code): \\(message)")
    } 

		//key에 해당하는 값 없음
		else {
        print("Unknown response \\(code)")
    }
}
// Prints "Response 200: OK"
// Prints "Response 403: Access forbidden"
// Prints "Unknown response 301"

 

Dictionary 추가, 삭제, 수정

  • subscripting을 사용하여 key와 value를 추가, 삭제, 수정을 할 수 있음
    • 새로 추가하는 key-value pair은 dictionary에 존재하지 않는 key-value로 추가해야함 (키는 유일성 보장)
  • key-value pair 삭제는 삭제하고자하는 key에 해당하는 value를 nil로 수정하면 영구적으로 삭제됨
// add key-value pair
responseMessages[301] = "Moved permaently"
print(responseMessages[301])
// Prints Optional("Moved permaently")

// update key-value pair
responseMessages[301] = "Deleted permanently"
print(responseMessages[301])
// Prints Optional("Deleted permanently")

// remove key-value pair
responseMessages[500] = nil
print(responseMessages)
// Prints [200: "OK", 301: "Deleted permanently", 403: "Access forbidden", 404: "File not found"]

responseMessages.removeValue(forKey: 404)
responseMessages.removeAll()

 

Dictionary의 프로퍼티와 메서드

  • isEmpty: 딕셔너리가 비어있다면 true, 비어있지 않다면 false 반환
  • count : 딕셔너리의 요소의 개수를 반환
  • removeValue(forKey: ) : key에 해당하는 value를 찾아 제거하고 그 값을 반환
    • 만약 딕셔너리 안에 key에 해당하는 value가 없다면 nil을 반환
    • 이 경우 기본값을 돌려주는 것도 가능
  • keys: 딕셔너리 안에 있는 모든 key를 배열로 반환
  • values: 딕셔너리 안에 있는 모든 value를 배열로 반환
  • contains(where:): 딕셔너리에 요소가 존재하면 true, 아니라면 false 반환
  • firstIndex(where:): 딕셔너리에 해당 요소의 첫 번째 인덱스를 optional로 반환
  • 딕셔너리이름 [ 키 ] = 값 : 딕셔너리에 키 와 값을 쌍을 추가
  • 딕셔너리이름 [ 키 ] = nil : 딕셔너리에서 키에 해당하는 값을 nil로 할당하여 제거
var intDictionary: [String: Int] = ["extramilejin": 28, "korea": 2021]

print(intDictionary.isEmpty)                        // false
print(intDictionary.count)                          // 2
print(intDictionary.removeValue(forKey: "korea"))   // Optional(2021)
print(intDictionary.count)                          // 1
print(intDictionary.removeValue(forKey: "korea"))   // nil: 값이 없음을 뜻한다.
print(intDictionary["korea", default: 0])           // 0: 값이 없으면 기본값 0

let countryCodes = ["BR": "Brazil", "GH": "Ghana", "JP": "Japan"]

print(countryCodes.keys) //["GH", "JP", "BR"]
print(countryCodes.values) //["Ghana", "Japan", "Brazil"]
print(countryCodes.contains(where: {$0.value == "Brazil"})) //true

 

 

Dictionary의 기본 값

  • 존재하지 않는 key를 사용하여 딕셔너리에서 value를 읽으려고하면  nil을 반환
  • 존재하지 않는 key에 대한 value를 요청하는 경우 기본값을 미리 할당할 수 있음
  • 딕셔너리에서 value에 증감 연산(+= 1, -= 1 … )을 하는 경우 사용
let favoriteIceCream = [ "서근": "초콜릿", "포뇨": "바닐라" ]
favoriteIceCream["서근"]
favoriteIceCream["하울"] // nil이 반환됨 -> 이는 해당 키에 대한 값이 없음을 의미함

//딕셔너리에 "Unknown"의 **기본값**을 지정하여이 nil이 반환되는 것을 방지
favoriteIceCream["하울", default: "Unknown"]

Dictionary의 반복

  • 딕셔너리 내부를 순회하기 위해, for-in loop를 사용해, key-value 쌍을 얻어 순회
  • key-value쌍은 튜플 형태로 반환
let imagePaths = ["star": "/glyphs/star.png",
                  "portrait": "/images/content/portrait.jpg",
                  "spacer": "/images/shared/spacer.gif"]

for (name, path) in imagePaths{
    print("The path to '\\(name)' is '\\(path)'.")
}
// The path to 'spacer' is '/images/shared/spacer.gif'.
// The path to 'star' is '/glyphs/star.png'.
// The path to 'portrait' is '/images/content/portrait.jpg'.

 

3. enum

enum의 정의

  • 열거형은 관련된 값 들의 그룹을 정의할 수 있도록 해주는 데이터 타입
  • 코드의 가독성과 안전성을 높여줌
  • 각기 다른 상태와 각기 다른 타입의 입력값을 나타내기 위해 사용
enum Direction {
    case north
    case south
    case east
    case west
}
  • 각 case에 대한 추가적인 정보 부여 가능
enum HTTPResponse {
    case success(Int)
    case error(Int, String)
}

enum의 역할 및 필요성

  • 가독성
    • 관련 값에 의미 있는 이름을 지정할 수 있으므로 코드를 더 읽기 쉽고 쉽게 이해할 수 있음
  • 안전성
    • 서로 다른 타입의 값이 잘못 변경되지 않도록함으로 형 안전성(type-safety)을 제공함
    • ex- Monday 타입의 값이 String 타입이 예상되는 곳에 잘못 사용되지 않도록 할 수 있음
  • 단순화
    • 열거형을 사용하면 작성해야 하는 코드의 양을 줄이고 코드를 보다 간결하게 만들 수 있음
    • 여러 개의 상수 또는 변수 선언을 단일 열거형 선언으로 대체 할 수 있음
  • 조직
    • 관련 값들을 열거형으로 그룹화하면 코드를 보다 효율적으로 구성할 수 있고 유지 관리도 쉽게 할 수 있음
  • 값 매칭
    • Swift의 스위치 구문은 열거형과의 값 매칭을 지원하므로 특정 값의 다양한 케이스를 쉽게 처리할 수 있음
    • 가능한 많은 수의 사례를 처리해야 할 때 특히 유용할 수 있음
enum HTTPResponse {
    case success(Int)
    case error(Int, String)
}

let response = HTTPResponse.success(200)

switch response {
case .success(let statusCode):
    print("Success with status code \\(statusCode)")
case .error(let statusCode, let message):
    print("Error with status code \\(statusCode) and message \\(message)")
}

 

enum의 사용법

enum Direction {
    case north
    case south
    case east
    case west
}

// To use an enum value, you simply reference its name:
let direction = Direction.north

switch direction {
case .north:
    print("Heading north")
case .south:
    print("Heading south")
case .east:
    print("Heading east")
case .west:
    print("Heading west")
}
  • enum 키워드를 사용해 열거형 정의
  • 여러 케이스를 콤마(,)로 구분하여 한 줄에 적을 수 있음
  • 완전 새로운 형 정의해야 함
    • Planet
    • 대문자로 시작해야 함
    enum Planet {
        case mercury, venus, earth, mars, jupiter, saturn, uranus, neptune
    } 
    
  • 형이 이미 한 번 정의된 경우, 다음에 값을 할당할 때에는 형을 생략한 점문법(dot syntax)을 이용해 값을 할당할 수 있음
var whereToGo = Planet.earth
whereToGo = .mercury

 

4. Set

Set의 정의

  • 같은 데이터 타입의 값을 순서 없이 저장하는 리스트
  • 중복을 허용하지 않음
var setName: Set = Set<Int>()

 

Set의 사용

count set의 항목의 개수 반환
isEmpty set이 비어있는지 확인
insert(value) set에 값 추가
remove(value) set에서 값 삭제
contains(value) set에 값이 존재하는지 확인
intersection(b) set b와 같은 요소들만 반환,  교집합
union(b) set b의 요소와 set의 요소 모두 부분 반환, 합집합
symmetricDifference(b) set b의 요소와 set의 요소에서 같은 요소만 빼고 반환
subtracting(b) set의 요소에서 set b와 같은 요소만 빼고 반환
반응형

'⌨️ Language > swift' 카테고리의 다른 글

[Swift] 예외 처리와 함수  (4) 2024.03.17
[Swift] 조건/반복문  (1) 2024.03.17
[Swift] 변수와 프로퍼티2  (1) 2024.03.15
[Swift] 변수와 프로퍼티1  (0) 2024.03.15
[Swift] Escaping Closure  (1) 2023.05.20

댓글