Collection
데이터 모음을 효율적으로 처리하기 위해서 사용하는 특별한 자료형
설명 | 예시 | |
Foundation Collection | 콜랙션을 참조 형식으로 사용해야할 때 객채형식의 데이터만 저장 가능 모든 자료형 가능 |
NSArray, NSDictionary, NSSet |
Swift Collection | 콜랙션을 값 형식으로 사용해야할 때 객체형식, 값 형식 모두 가능 동일한 자료형만 저장 가능 |
Array, Dictionary, Set |
Copy - on - write
Swift Collection은 값 형식으로 반드시 복사가 필요한 경우만 복사를 실행함, 콜랙션이 변경되지 않는다면 항상 동일한 데이터 사용, 특정 시점에 콜랙션을 변경한다면 그 시점에 복사본을 생성하고 변경사항 적용
Array
데이터를 순서대로 저장하는 콜랙션, 배열은 순서에 따라 index 번호가 부여되는데 배열의 마지막을 추가, 삭제 할 경우 큰 문제가 없지만 배열의 중간에서 추가, 삭제를 할 경우 뒤에 있는 요소들이 이동해야 되기 때문에 오버헤드 발생
// Array Literal
[elem, elem, ...]
// Array Type
Array<T>
[T]
Creating an Array
let nums = [1, 2, 3]
let emptyArray : [Int] = []
let emptyArray2 : Array<Int>()
let emptyArray3 : [Int]()
let zeroArray = [Int](repeating : 0, count : 10)
Inspecting an Array
let nums = [1, 2, 3]
nums.count // 3
nums.count == 0 // false
nums.isEmpty // false
Accessing Elements
배열에 접근할 때 배열의 갯수, 순서 등에 잘못 접근하면 오류가 발생하기 때문에 서브 스크립트 문법보다 프로퍼티로 접근하는 게 더 안전함
let fruits = ["Apple", "Banana", "Melon"]
fruits[0] // "Apple"
fruits[0...1] // "Apple", "Banana"
fruits[fruits.startIndex] // "Apple"
fruits[fruits.index(before : fruits.endIndex)] // "Melon"
fruits.first // "Apple"
fruits.last // "Melon"
Adding Elements
insert의 경우 중간에 배열을 추가할 경우 오버헤드 발생하기 때문에 append로 맨 앞이나 맨 뒤에 추가하는것을 권장
var alphabet = ["A", "B", "C"]
alphabet.append("E") //["A", "B", "C", "E"]
alphabet.append(contentsOf : ["F", "G"]) // ["A", "B", "C", "E", "F", "G"]
alphabet.insert("D", at : 3) // ["A", "B", "C", "D", "E", "F", "G"]
alphabet.insert(contentsOf : ["a", "b", "c"], at : 0) // ["a", "b", "c", "A", "B", "C", "D", "E", "F", "G"]
alphabet.[0...2] = ["x", "y", "z"] // ["x", "y", "z", "A", "B", "C", "D", "E", "F", "G"]
alphabet.replaceSubrange(0...2, with : ["a", "b", "c"]) // ["a", "b", "c", "A", "B", "C", "D", "E", "F", "G"]
alphabet.[0...2] = ["z"] // ["z", "A", "B", "C", "D", "E", "F", "G"]
alphabet.[0..<1] = [] // ["A", "B", "C", "D", "E", "F", "G"]
Removing Elements
var alphabet = ["A", "B", "C", "D", "E", "F", "G"]
alphabet.remove(at : 2) // "C"
alphabet // ["A", "B", "D", "E", "F", "G"]
alphabet.removeFirst() // ["A"]
alphabet // ["B", "D", "E", "F", "G"]
alphabet.removeFirst(2) // return X
alphabet // ["E", "F", "G"]
alphabet.removeAll() // []
alphabet.popLast() // nil
var alphabet = ["A", "B", "C", "D", "E", "F", "G"]
alphabet.popLast() // "G"
alphabet // ["A", "B", "C", "D", "E", "F"]
alphabet.removeSubrange(0...2) // ["D", "E", "F"]
alphabet.[0...2] = [] // ["D", "E", "F"]
alphabet // []
Comparing Arrays
let a = ["A", "B", "C"]
let a = ["a", "b", "c"]
a == b // false
a != b // true
a.elementsEqual(b) // false
a.elementsEqual(b) {(lhs, rhs) -> Bool in
return lhs.caseInsensitiveCompare(rhs) == .orderedSame //true
Finding Arrays
let nums = [1, 2, 3, 1, 4, 5, 2, 6, 7, 5, 0]
nums.contains(1) // true
nums.contains(8) // false
nums.contain { (n) -> Bool in // true
return n % 2 == 0
}
nums.first { (n) -> Bool in // 2
return n % 2 == 0
}
nums.firstIndex { (n) -> Bool in // 1
return n % 2 == 0
}
nums.firstIndex(of : 1) // 0
nums.lastIndex(of : 1) //3
Sorting on Arrays
sort -> 배열을 직접 정렬, 새로운 배열 리턴 X
sorted 정렬된 새로운 배열을 리턴
let nums = [1, 2, 3, 1, 4, 5, 2, 6, 7, 5, 0]
nums.sorted() // [0, 1, 1, 2, 2, 3, 4, 5, 5, 6, 7]
nums // [1, 2, 3, 1, 4, 5, 2, 6, 7, 5, 0]
nums.sorted{ (a, b) -> Bool in // [7, 6, 5, 5, 4, 3, 2, 2, 1, 1, 0]
return a > b
}
nums.sorted().reversed()
[Int](nums.sorted().reversed()) // [7, 6, 5, 5, 4, 3, 2, 2, 1, 1, 0]
var mutableNums = nums // [1, 2, 3, 1, 4, 5, 2, 6, 7, 5, 0]
mutableNums.sort() // [0, 1, 1, 2, 2, 3, 4, 5, 5, 6, 7]
mutableNums.reverse() // [7, 6, 5, 5, 4, 3, 2, 2, 1, 1, 0]
mutableNums // [7, 6, 5, 5, 4, 3, 2, 2, 1, 1, 0]
mutableNums.swapAt(0, 1) // [6, 7, 5, 5, 4, 3, 2, 2, 1, 1, 0]
mutableNums.shuffle() // 요소의 순서 랜덤 변환
mutableNums.shuffled() // 요소의 순서 랜덤 변환 후 리턴
Dictionary
키와 값을 하나의 쌍으로 저장하는 콜랙션, 키는 유일한 값을 가져야 함, 정렬하지 않는 콜랙션
[key : value, key : value, ...]
var dict = ["A" : "Apple", "B" : "Banana"]
dict = [:]
Dictionary Type
Dictionary<K,V>
[K : V]
let dict1 : Dictionary<String, Int>
let dict2 : [String : Int]
Creating a Dictionary
let words = ["A" : "Apple", "B" : "Banana", "C" : "City"]
let emptyDict : [String : String] = []
let emptyDict2 = [String : String]()
let emptyDict3 = Dictionary<String : String>()
Inspecting a Dictionary
let words = ["A" : "Apple", "B" : "Banana", "C" : "City]
words.count // 3
words.isEmpty // false
Accessign Keys and Values
let words = ["A" : "Apple", "B" : "Banana", "C" : "City"]
words["A"] // "Apple"
words["Apple"] // nil
let a = words["E"] // nil
let b = words["E", default : "Empty"] //Empty
for k in words.keys.sortecd() // A, B, C
print(k)
}
for v in words.value { // Banana, Apple, City
print(v)
}
let keys = Array(words.keys)
let values = Array(words.values)
Adding Keys and Values
var words = [String : String]()
words["A"] = "Apple" // "A" : "Apple"
words["B"] = "Banana" // "A" : "Apple", "B" : "Banana"
words["B"] = "Ball" // "A" : "Apple", "B" : "Ball"
words.updateValue("City", forKey : "C") // nil / "A" : "Apple", "B" : "Ball", "C" : "City"
words.updateValue("Circle", forKey : "C") // City / 이전에 저장된 값 리턴
만약 기존에 값이 없었다면 추가 insert
기존에 값이 있다면 업데이트 update
insert + update = upsert
Removing Keys and Values
let words = ["A" : "Apple", "B" : "Banana", "C" : "Circle"]
words["B"] = nil // ["A" : "Apple", "C" : "Circle"]
words["Z"] = nil // nil // 존재하지 않는 코드일 경우 다음 코드 실행
words.removeValue(forKey : "A") // "Apple" / 삭제되는 값 리턴
words.removeValue(forKey : "A") // nil / 존재하지 않는 코드일 경우 다음 코드 실행
words.removeAll() // 전체 삭제
Comparing Dictionaries
let a = ["A" : "Apple", "B" : "Banana", "C" : "City"]
let b = ["A" : "Apple", "C" : "City", "B" : "Banana"]
a == b // true
a != b // false
let a = ["A" : "Apple", "B" : "Banana", "C" : "City"]
let b = ["A" : "Apple", "C" : "City", "B" : "banana"]
a == b // false // 대소문자도 구별
a != b // true
a.elemetsEqual(b) {(lhs, rhs) -> Bool in
return lhs.key.caseInsensitiveCompare(rhs.key) == .orderSame &&
lhs.value.caseInsensitiveCompare(rhs.key) == .orderSame
} // true 혹은 false를 리턴, 딕셔너리는 정렬되지 않은 배열이기 때문에 코드를 실행할 때 마다
// 다른 배열형태로 전달되기 때문에 ture 혹은 false로 리턴
let aKeys = a.keys.sorted()
let bKeys = b.keys.sorted()
aKeys.elementsEqual(bkeys) { (lhs, rhs) -> Bool in // true
guard lhs.key.caseInsensitiveCompare(rhs) == .orderSame else {
return false
}
guard let lv = a[lhs], let rv = b[rhs], lv.caseInsensitiveCompare(rhs) == .orderSame else {
return false
}
return true
}
Finding Elemets
let words = ["A" : "Apple", "B" : "Banana", "C" : "City"]
let c : ((String, String)) -> Bool = { // true
$0.0 == "B" || $0.1.contains("i")
}
words.contains(where : c) //true
let r = words.first(where : c)
r?.key
r?.value
// 처음으로 검색된 결과를 리턴, 하지만 딕셔너리는 정렬되지 않는 배열이기 때문에 값이 매번 달라짐
words.filter(c) // ["C" : "City", "B" : "Banana"]
// 조건을 만족시키는 값이 새로운 딕셔너리에 배열됨
Set
집합 연산을 제공하는 콜랙션, 정렬순서보다 검색속도가 중요한 경우 사용, 배열처럼 하나의 데이터를 하나의 요소로 저장, 정렬되지 않고 인덱스도 사용하지 않음, 동일한 값을 하나만 저장
Set Type
Set<T>
let set : Set<Int> = [1, 2, 2, 3, 3, 3] // 1, 2, 3
set.count // 3
InspectingType
let set : Set<Int> = [1, 2, 2, 3, 3, 3] // 1, 2, 3
set.count // 3
set.isEmpty // false
Testing for Membership
let set : Set<Int> = [1, 2, 2, 3, 3, 3] // 1, 2, 3
set.contains(1) // true
Adding and Removing Elements
var words = Set<String>()
var insertResult = words.insert("Swift")
insertResult.inserted // true
insertResult.memberAfterInsert // "Swift"
// Set은 중복을 허용하지 않음
var insertResult = words.insert("Swift")
insertResult.inserted // false
insertResult.memberAfterInsert // "Swift"
// Upsert 방식 사용
var updateResult = words.update(with : "Swift") // "Swift"
updateResult // "Swift"
var updateResult = words.update(with : "Apple") // nil
updateResult // "nil
words.remove("Swift")
words.removeAll()
Comparing Sets
var a : Set = [1, 2, 3, 4, 5, 6, 7, 8, 9]
var b : Set = [1, 3, 5, 7, 9]
var c : Set = [2, 4, 6, 8, 10]
var d : Set = [1, 7, 5, 9, 3]
a == b // false
a != b // true
b == d // true
a.isSubset(of : a) //true
a.isStrictSubset(of : a) //false
b.isSubset(of : a) //true
b.isStrictSubset(of : a) //true
a.isSuperset(of : a) //true
a.isStrictSuperset(of : a) //false
a.isSuperset(of : b) //true
a.isStrictSuperset(of : b) //true
a.isSuperset(of : c) //false
a.isStrictSuperset(of : c) //false
a.isDisjoint(with : b) // false 교집합O
a.isDisjoint(with : c) // false 교집합O
a.isDisjoint(with : c) // true 교집합x
Combining Sets
합집합은 union을 사용하고 두 변수를 합친 후에 새로운 Set을 리턴, formUnion은 원본을 변경
a = [1, 2, 3, 4, 5, 6, 7, 8, 9,]
b = [1, 3, 5, 7, 9]
c = [2, 4, 6, 8, 10]
var result = b.union(c) // 3, 4, 10, 6, 1, 9, 8, 2, 5, 7
result = b.union(a) // 3, 6, 4, 1, 9, 8, 2, 5, 7
// form은 원본을 변경
b.formUnion(c) // 3, 4, 10, 6, 1, 9, 8, 2, 5, 7
b // 3, 4, 10, 6, 1, 9, 8, 2, 5, 7
교집합은 intersection을 사용하고 두 변수의 공통요소를 새로운 Set을 리턴, formIntersection은 원본을 변경
a = [1, 2, 3, 4, 5, 6, 7, 8, 9,]
b = [1, 3, 5, 7, 9]
c = [2, 4, 6, 8, 10]
result = a.intersection(b) // 1, 5, 3, 9, 7
result = c.intersection(b) // Set[]
a.formIntersection(b) // 1, 5, 3, 9, 7
a // 1, 5, 3, 9, 7
b.formIntersection(c) // Set[]
여집합은 symmetricDifference을 사용하고 새로운 Set을 리턴, formsymmetricDifference는 원본을 변경
a = [1, 2, 3, 4, 5, 6, 7, 8, 9,]
b = [1, 3, 5, 7, 9]
c = [2, 4, 6, 8, 10]
result = a.symmetricDifference(b) // 6, 8, 2, 4
result = a.symmetricDifference(b) // 3, 10, 6, 7, 1, 9, 8, 2, 4, 5
result = a.formsymmetricDifference(b) // 6, 8, 2, 4
a // 6, 8, 2, 4
차집합은 subtracting을 사용하고 새로운 Set을 리턴, subtract는 원본을 변경
a = [1, 2, 3, 4, 5, 6, 7, 8, 9,]
b = [1, 3, 5, 7, 9]
c = [2, 4, 6, 8, 10]
reuslt = a.subtracting(b) // 6, 8, 2, 4
a.subtract(b) // 6, 8, 2, 4
Iterating Collections
컬랙션을 열거하는 방법
for in
for element in collection {
statements
}
// Array 열거
let arr = [1, 2, 3]
for num in arr {
print(num)
}
// 1, 2, 3
// Set 열거
let set : Set = [1, 2, 3]
for num in set {
print(num)
}
// 1, 3, 2 / 정렬하지 않기 떄문에 결과의 순서가 매번 다름
// Dictionary 열거
let dict = ["A" : 1, "B" : 2, "C" : 3]
for (key, value) in dict {
print(key, value)
}
// C 3, A 1, B 2 / 정렬하지 않기 떄문에 결과의 순서가 매번 다름
forEach
// Array 열거
let arr = [1, 2, 3]
arr.forEach { (num) in
print(num)
}
// 1, 2, 3
// Set 열거
let set : Set = [1, 2, 3]
set.forEach { (num) in
print(num)
}
// 1, 3, 2 / 정렬하지 않기 떄문에 결과의 순서가 매번 다름
// Dictionary 열거
let dict = ["A" : 1, "B" : 2, "C" : 3]
dict.forEach { (elem) in
print(elem.key, elem.value)
}
// C 3, A 1, B 2 / 정렬하지 않기 떄문에 결과의 순서가 매번 다름
for in vs forEach
func withForIn() {
print(#function)
let arr = [1, 2, 3]
for num in arr {
print(num)
return
}
}
// 1
func withForEach() {
print(#function)
let arr = [1, 2, 3]
arr.forEach { (num) in
print(num)
return
}
}
// 1, 2, 3
for in | forEach |
반복문으로 break, continue 사용 가능 | 매서드로 break, continue 사용 불가능 |
return 동작방식이 반복문 코드문이 바로 종료 | forEach 클로저로 전달한 클로저 내부에서 호출한 리턴문은 외부에는 영향을 주지 않고 반복횟수에도 영향을 주지 않고 지금 실행하고 있는 클로저 코드에만 영향을 줌 |
'스피드 문법정리' 카테고리의 다른 글
14. Structure and Class (0) | 2020.06.18 |
---|---|
13. Enumeration (0) | 2020.06.17 |
9. Functions (0) | 2020.06.15 |
7. Control Transfer Statements, Labeled Statements (0) | 2020.06.12 |
6. Loop Statements (0) | 2020.06.12 |