Search

[Swift 공식 문서] 4. Collection Types

요약

변경하지 않는 collection 은 반드시 상수로 선언할 것
remove() → 동일항목 존재 시 제거 및 리턴 (optional)

Collection Types

Swift에는 3가지의 중요한 컬렉션 타입이 있는데요.
1.
Array
2.
Set
3.
Dictionary
이들의 특징은 아래와 같습니다.
1.
Array : 순서 O
2.
Set : 순서 X 유일한 값
3.
Dictionary : 순서 X key-value 타입
Swift 의 Array, Set, Dictionary 에는 항상 저장할 key 와 value 가 명확해야 하는데요. 명시한 타입과는 다른 타입의 value 는 collection 에 삽입할 수 없습니다.

Mutability of Collections

Array, Set, Dictionary 를 변수로 선언하면, 이 collection 들은 변경 가능(mutable)합니다. 생성 후에 이 collection 내의 항목들을 추가, 제거, 변경 들이 가능합니다.
Array, Set, Dictionary 를 상수로 선언하면 이 collection 들은 변경 불가(immutable)합니다.
변경하지 않는 collection 은 반드시 상수로 선언하세요. 상수로 선언하면 Swift 컴파일러가 그에맞게 성능을 최적화 합니다.

Arrays

같은 타입의 값들을 순서가 있는 list 의 형태로 저장합니다.
중복된 값이 다른 위치에 저장될 수 있습니다.
Swift 의 Array 는 NSArray 와 호환이 가능합니다.

Array Type Shorthand Syntax

array 의 타입은 Array<Element> 로 Element 에는 저장되는 value 의 타입이 들어갑니다.
[Element] 로도 타입을 명시할 수 있습니다.

Creating an Empty Array - 빈 어레이 생성하기

생성자 구문을 활용해 특정 타입의 빈 어레이를 생성할 수 있다.
var someInts: [Int] = [] print("someInts is of type [Int] with \(someInts.count) items.") // Prints "someInts is of type [Int] with 0 items."
Swift
복사
이미 어레이의 타입이 분명한 경우 빈 어레이 literal [] 을 사용해서 빈어레이를 만들 수 있다.
someInts.append(3) // someInts now contains 1 value of type Int someInts = [] // someInts is now an empty array, but is still of type [Int]
Swift
복사

Creating an Array with a Default Value - 초기값을 가지는 어레이 생성

같은 초기값을 가지는 특정 사이즈의 어레이를 생성자를 활용해 만들 수 있다.
var threeDoubles = Array(repeating: 0.0, count: 3) // threeDoubles is of type [Double], and equals [0.0, 0.0, 0.0]
Swift
복사
repeating : 반복되는 초기값
count : 반복 횟수

Creating an Array by Adding Two Arrays Together 두 어레이를 더해서 생성

이미 존재하는 두 어레이를 더해서 새 어레이를 생성할 수 있다.
단, 두 어레이의 원소 타입이 같아야하며,
새 어레이의 타입 또한 더해진 어레이로 부터 추론된다.
var anotherThreeDoubles = Array(repeating: 2.5, count: 3) // anotherThreeDoubles is of type [Double], and equals [2.5, 2.5, 2.5] var sixDoubles = threeDoubles + anotherThreeDoubles // sixDoubles is inferred as [Double], and equals [0.0, 0.0, 0.0, 2.5, 2.5, 2.5]
Swift
복사

Creating an Array with an Array Literal

Array 리터럴 을 이용해 새 어레이를 생성할 수 있다.
[value 1, value 2, value 3]
var shoppingList: [String] = ["Eggs", "Milk"] // shoppingList has been initialized with two initial items
Swift
복사
shoppingList 변수는 [String] 타입으로 선언 되었으므로 이 어레이에는 String 타입 만이 저장될 수 있다.

Accessing and Modifying an Array

메서드,프로퍼트,첨자 구문을 통해 어레이를 변경 또는 접근할 수 있다.
1.
count : 어레이의 길이 리턴
print("The shopping list contains \(shoppingList.count) items.") // Prints "The shopping list contains 2 items."
Swift
복사
2.
isEmpty : 어레이가 0 인지 확인
if shoppingList.isEmpty { print("The shopping list is empty.") } else { print("The shopping list isn't empty.") } // Prints "The shopping list isn't empty."
Swift
복사
3.
append() : 새 항목 추가
shoppingList.append("Flour") // shoppingList now contains 3 items, and someone is making pancakes
Swift
복사
4.
+= : 어레이 병합
shoppingList += ["Baking Powder"] // shoppingList now contains 4 items shoppingList += ["Chocolate Spread", "Cheese", "Butter"] // shoppingList now contains 7 items
Swift
복사
5.
인덱싱
var firstItem = shoppingList[0] // firstItem is equal to "Eggs"
Swift
복사
첨자 접근 시 존재하지 않는 인덱스에 대해 접근하려 하면 런타임 에러 발생!!
subscript 구문활용시 특정 범위의 값에 한번에 접근가능.
shoppingList[4...6] = ["Bananas", "Apples"] // shoppingList now contains 6 items
Swift
복사
6.
insert() : 특정 인덱스에 항목 삽입
shoppingList.insert("Maple Syrup", at: 0) // shoppingList now contains 7 items // "Maple Syrup" is now the first item in the list
Swift
복사
7.
remove(at: ) : 특정 인덱스 항목 제거
let mapleSyrup = shoppingList.remove(at: 0) // the item that was at index 0 has just been removed // shoppingList now contains 6 items, and no Maple Syrup // the mapleSyrup constant is now equal to the removed "Maple Syrup" string
Swift
복사
어레이의 경계 너머의 인덱스에 값을 변경 또는 접근하려 한다면 런타임 에러 발생합니다. 유효한 인덱스 중 가장 큰 수는 count - 1 입니다. (단 count = 0 일 경우 접근 가능한 인덱스가 존재하지 않음)
값이 제거되고 난 후의 항목들은 빈자리를 채웁니다.
firstItem = shoppingList[0] // firstItem is now equal to "Six eggs"
Swift
복사
어레이의 마지막 항목을 삭제하고 싶다면, remove(at: ) 보다는
removeLast() 메서드를 사용하세요. 이를 활용하면 어레이의 count 프로퍼티를 확인하지 않고 맨 마지막 원소를 제거할 수 있습니다. 또한 이 메서드는 제거된 항목을 리턴합니다.
let apples = shoppingList.removeLast() // the last item in the array has just been removed // shoppingList now contains 5 items, and no apples // the apples constant is now equal to the removed "Apples" string
Swift
복사

Iterating Over an Array

for - in loop 내에서 어레이의 전체 값을 순회할 수 있습니다.
for item in shoppingList { print(item) } // Six eggs // Milk // Flour // Baking Powder // Bananas
Swift
복사
인덱스와 값을 함께 순회하고 싶다면,
enumerated() 메서드를 사용하세요
이 메서드는 정수 인덱스와 그 항목으로 구성된 튜플을 리턴합니다.
튜플을 decompose 해서 for in 루프에서 각각의 값을 따로 사용할 수 있습니다.
for (index, value) in shoppingList.enumerated() { print("Item \(index + 1): \(value)") } // Item 1: Six eggs // Item 2: Milk // Item 3: Flour // Item 4: Baking Powder // Item 5: Bananas
Swift
복사

Set 집합

Set 이란 같은 타입의 원소들을 중복 없이 저장합니다. set 에는 순서가 없습니다.
1.
순서가 중요하지 않거나,
2.
중복된 항목을 원하지 않는다거나
하는 경우에는 Array 보다 Set 이 적합합니다.
Set 타입은 Foundation 의 NSSet 클래스와 브릿징 됩니다.

Hash Values for Set Types

set 에 값을 저장하기 위해서는 값의 타입이 반드시 Hashable 프로토콜을 준수해야합니다.
type 은 hash value 를 스스로 계산하여 제공합니다.
Hash value 는 정수 타입의 값이며, 동등한 모든 객체에 대해서 항상 같은 값을 가집니다.
Swift 의 모든 기본 타입들 ( String, Int, Double, Bool ) 들은 기본적으로 hashable 합니다.
hashable 한 타입들은 기본적으로 set 의 value 또는 dictionary 의 key 로 사용이 가능합니다.
연관된 값이 없는 Enumeration case 값 또한 기본적으로 hashable 합니다.
커스텀 타입 또한 Hashable 프로토콜을 준수해 줌으로 써 dictionary 의 key 또는 set 의 value 로 사용이 가능합니다.

Set Type Syntax

Swift 의 set 은 Set<Element> 타입으로 작성합니다. 여기서 Element 는 set 이 저장할 값의 타입을 의미합니다. 어레이와는 다르게 축약된 형식이 존재하지 않습니다.

Creating and Intializing an Empty Set

특정 type 의 빈 set 을 생성자를 활용해 만들 수 있습니다.
var letters = Set<Character>() print("letters is of type Set<Character> with \(letters.count) items.") // Prints "letters is of type Set<Character> with 0 items."
Swift
복사
맥락상 타입이 이미 정해져 있는 경우, 빈 어레이 리터럴을 활용해 텅 빈 set 을 생성할 수 있습니다.
letters.insert("a") // letters now contains 1 value of type Character letters = [] // letters is now an empty set, but is still of type Set<Character>
Swift
복사

Creating a Set with an Array Literal

어레이 리터럴을 활용해서 set 의 initialize 가 가능합니다.
단 항상 set 의 타입을 명시해 주어야합니다. (어레이 리터럴 만으로는 선언이 불가능합니다.)
var favoriteGenres: Set<String> = ["Rock", "Classical", "Hip hop"] // favoriteGenres has been initialized with three initial items
Swift
복사
어레이 리터럴 내의 원소들에 대해 타입 추론이 가능하기 때문에 아래와 같이 짧게 선언할 수도 있습니다.
var favoriteGenres: Set = ["Rock", "Classical", "Hip hop"]
Swift
복사

Accessing and Modifying a Set

아래의 메서드와 프로퍼티를 통해 set 에 접근 및 수정이 가능합니다.
1.
count : 원소의 개수를 리턴
2.
isEmpty : 원소의 개수가 0인지 확인
3.
insert() : 항목 추가
4.
remove() : 특정 항목 제거 및 제거한 항목 리턴 ( 옵셔널한 타입을 리턴한다)
존재하지 않는 값에대해 제거를 시도하면 nil 값을 리턴
리턴 타입이 optional 이므로 옵셔널 바인딩을 통해서 값에 접근 가능하다.
if let removedGenre = favoriteGenres.remove("Rock") { print("\(removedGenre)? I'm over it.") } else { print("I never much cared for that.") } // Prints "Rock? I'm over it."
Swift
복사
5.
contains() : 특정 항목이 존재하는 지 확인

Iterating Over a Set

for in loop 에서 순회가 가능하다
for genre in favoriteGenres { print("\(genre)") } // Classical // Jazz // Hip hop
Swift
복사
Set 타입에는 순서가 없으므로, 특정 순서에 따라 값을 순회하고 싶다면,
sorted() 메서드를 사용하자.
이 메서드는 < 연산자를 사용해 set 의 원소들을 정렬, 어레이를 리턴한다.
for genre in favoriteGenres.sorted() { print("\(genre)") } // Classical // Hip hop // Jazz
Swift
복사

Performing Set Operations

1.
intersection(_:) : 교집합
2.
symmetricDifferernce(_:) :
3.
union() : 합집합
4.
subtracting() : 차집합
let oddDigits: Set = [1, 3, 5, 7, 9] let evenDigits: Set = [0, 2, 4, 6, 8] let singleDigitPrimeNumbers: Set = [2, 3, 5, 7] oddDigits.union(evenDigits).sorted() // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] oddDigits.intersection(evenDigits).sorted() // [] oddDigits.subtracting(singleDigitPrimeNumbers).sorted() // [1, 9] oddDigits.symmetricDifference(singleDigitPrimeNumbers).sorted() // [1, 2, 9]
Swift
복사

Set Membership and Equality

Use the “is equal” operator (==) : 두 집합이 완전히 같은 값을 가지고 있는지 확인
Use the isSubset(of:) method : 부분집합인지 확
Use the isSuperset(of:) method : 모집합인지 확인
Use the isStrictSubset(of:) or isStrictSuperset(of:) methods : 두 집합이 같지 않으면서 부분집합 또는 모집합인지 확인
Use the isDisjoint(with:) method : 두 집합이 서로 독립인지 확인
let houseAnimals: Set = ["🐶", "🐱"] let farmAnimals: Set = ["🐮", "🐔", "🐑", "🐶", "🐱"] let cityAnimals: Set = ["🐦", "🐭"] houseAnimals.isSubset(of: farmAnimals) // true farmAnimals.isSuperset(of: houseAnimals) // true farmAnimals.isDisjoint(with: cityAnimals) // true
Swift
복사

Dictionaries

딕셔너리는 같은 타입의 키들과 같은 타입의 값들 의 쌍을 순서없이 저장합니다. 각각의 값들은 유일한 key 와 한쌍을 이루어 각 값들에 대한 식별자 역할을 수행합니다. 어레이와는 다르게 항목들이 순서를 가지지 않습니다. 식별자를 활용해 값을 찾을 필요가 있는 경우 딕셔너리를 사용합니다.
Swift 의 Dictionary 타입은 Foundation 의 NSDictionary 클래스와 브릿징 됩니다.

Dictionary Type Shorthand Syntax

딕셔너리의 타입은 Dictionary<Key, Value> 라고 쓰며, Key 는 딕셔너리의 키로 사용될 데이터의 타입, Value 는 딕셔너리의 value 로 사용될 데이터의 타입을 나타냅니다.
딕셔너리의 Key 타입은 반드시 Hashable 프로토콜을 준수해야합니다.
축약된 형태인 [Key: Value] 로도 타입선언이 가능합니다. 두 선언 방법 모두 기능적으로 동일합니다.

Creating an Empty Dictionary

어레이에서 처럼 initializer 를 활용해 특정 타입의 빈 Dictionary 를 생상헐 수 있습니다.
var namesOfIntegers: [Int: String] = [:] // namesOfIntegers is an empty [Int: String] dictionary
Swift
복사
맥락상 타입 정보가 분명할 경우, [:] 리터럴을 사용해서 빈 딕셔너리를 생성할 수 있습니다
namesOfIntegers[16] = "sixteen" // namesOfIntegers now contains 1 key-value pair namesOfIntegers = [:] // namesOfIntegers is once again an empty dictionary of type [Int: String]
Swift
복사

Creating a Dictionary with a Dictionary Literal

또한 딕셔너리 리터럴을 사용해 딕셔너리를 초기화할 수 있습니다. ( 단 딕셔너리의 키밸류 타입과 리터럴의 키밸류 타입이 일치해야 사용이 가능합니다 )
var airports: [String: String] = ["YYZ": "Toronto Pearson", "DUB": "Dublin"]
Swift
복사

Accessing and Modifying a Dictionary

아래의 메서드를 활용해 딕셔너리를 접근 또는 수정할 수 있습니다.
1.
count : 항목의 개수를 반환
2.
isEmpty : 항목의 개수가 0 인지 확인
3.
updateValue(_ forKey: ) : 특정 키밸류 쌍 추가.
만약 이미 존재하는 Key 에대해 사용하게 되면 이 메서드는 이전의 Value 를 반환합니다. 만약 해당 Key 가 존재하지 않는다면, 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."
Swift
복사
4.
첨자를 활용한 새항목 추가
적절한 타입의 새로운 Key를 활용한 첨자접근에 Value 를 할당하게 되면 새항목이 추가됩니다. 이때 이미 존재하는 Key 에 대해서는 새로이 값을 갱신합니다.
airports["LHR"] = "London" // the airports dictionary now contains 3 items airports["LHR"] = "London Heathrow" // the value for "LHR" has been changed to "London Heathrow"
Swift
복사
5.
키를 활용한 첨자 접근
키값을 활용해 value 에 접근시 리턴 타입은 Optional 하다. 따라서 옵셔널 바인딩을 통해 다음과 같이 값에 접근이 가능하다
if let airportName = airports["DUB"] { print("The name of the airport is \(airportName).") } else { print("That airport isn't in the airports dictionary.") } // Prints "The name of the airport is Dublin Airport."
Swift
복사
6.
removeValue(forKey:) : 해당 Key 를 가지는 키밸류 쌍을 제거 및 Value 반환
리턴 타입이 Optional 합니다 만약 해당 Key 값이 존재하지 않는 다면 nil 값을 리턴합니다.
if let removedValue = airports.removeValue(forKey: "DUB") { print("The removed airport's name is \(removedValue).") } else { print("The airports dictionary doesn't contain a value for DUB.") } // Prints "The removed airport's name is Dublin Airport."
Swift
복사

Iterating Over a Dictionary

for in loop 에서 딕셔너리의 key value 쌍들을 순회할 수 있습니다. 각각의 항목은 (key, value) 형태의 튜플을 반환합니다. 이를 decompose 해서 각각의 값들을 사용할 수 있습니다.
for (airportCode, airportName) in airports { print("\(airportCode): \(airportName)") } // LHR: London Heathrow // YYZ: Toronto Pearson
Swift
복사
key 값만을 가지고 순회하고 싶다면 keys 프로퍼티를 사용할 수 있습니다.
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
Swift
복사
만약 딕셔너리의 key 또는 value 들을 어레이 객체를 필요로 하는 API 에 사용해야한다면, keys 또는 value 프로퍼티와 어레이 initializer 를 활용할 수 있습니디.
let airportCodes = [String](airports.keys) // airportCodes is ["LHR", "YYZ"] let airportNames = [String](airports.values) // airportNames is ["London Heathrow", "Toronto Pearson"]
Swift
복사
Swift 의 Dictionary 타입은 순서가 없습니다. 특정 순서를 이용하고 싶다면 sorted() 메서드를 keys 또는 values 프로퍼티에 사용하세요.