
Swift는 콜렉션의 값을 저장하기 위한 배열 (array), 집합 (set), 딕셔너리 (dictionary) 와 같은 3개의 원시적인 콜렉션 타입 (collection types) 을 제공한다.
- 배열 (array) : 콜렉션 값에 순서를 가지고있다.
- 집합 (set) : 반복되지 않은 값에 순서가 없는 콜렉션 타입이다.
- 딕셔너리 (dictionary) : 키-값 쌍의 순서가 없는 콜렉션 타입이다.
: 변수에 할당한 경우는 변경 가능(mutable)
: 콜렉션이 생성된 이후에 아이템을 추가, 삭제, 변경할 수 있다.
: 상수에 할당한 경우는 변경 불가능(immututable)
: 객체가 초기화된 이후에 크기와 콘텐츠를 변경될 수 없다.
: 순서 있는 컬렉션에 여러 값을 담기 위하여 설계된 데이터 타입
var 변수명: [타입] = [값1, 값2, 값3, .........]
초기화 구문을 사용하여 타입을 포함한 빈 배열을 생성할 수 있다.
var someInts: [Int] = []
print("someInts is of type [Int] with \(someInts.count) items.")
// 출력 "someInts is of type [Int] with 0 items."
someInts 변수의 타입은 초기화 타입을 통해 [Int]로 추론된다.
[] (빈 대괄호 쌍)으로 빈 배열을 생성할 수 있다.
var 변수명 = [타입] ()
someInts.append(3)
// someInts Int형 변수 하나를 포함하는 배열이다.
someInts = []
// someInts를 빈 배열로 생성, 여전히 타입을 Int배열
var piceArray = [Float]()
//부동소수점 값을 저장하도록 설계한 빈 배열을 생성
//priceArray라는 변수에 할당
기본 값으로 설정하고 크기를 고정하여 배열을 생성하는 초기화도 제공한다.
적합한 타입의 기본값과 새로운 배열에 반복될 값의 횟수를 초기화에 전달한다.
var threeDoubles = Array(repeating: 0.0, count: 3)
//repeating : 적합한 타입의 기본 값
//count : 새로운 배열에 반복될 값의 횟수
// threeDoubles 타입 : [Double]
// threeDoubles = [0.0, 0.0, 0.0]
동등한 타입의 2개의 존재하는 배열을 덧셈 연산자 (+)를 통해 합쳐서 새로운 배열을 생성할 수 있다.
var anotherThreeDoubles = Array(repeating: 2.5, count: 3)
// anotherThreeDoubles 타입 : [Double]
// anotherThreeDoubles = [2.5, 2.5, 2.5]
var sixDoubles = threeDoubles + anotherThreeDoubles
// sixDoubles 타입 : [Double]
// sixDoubles = [0.0, 0.0, 0.0, 2.5, 2.5, 2.5]
메서드와 프로퍼티 또는 서브 스크립트 구문을 사용하여 배열에 접근 및 수정이 가능하다.
count 프로퍼티 : 배열의 아이템 갯수print("The shopping list contains \(shoppingList.count) items.")
// 출력 "The shopping list contains 2 items."
isEmpty 프로퍼티 : 배열의 count 프로퍼티 값이 0인지 아닌지 판단**if shoppingList.isEmpty {
print("The shopping list is empty.")
} else {
print("The shopping list is not empty.")
}
// 출력 "The shopping list is not empty."
shoppingList.append("Flour")
// shoppingList는 3개의 아이템을 갖게 된다.
shoppingList += ["Baking Powder"]
// shoppingList는 4개의 아이템을 갖게 된다.
shoppingList += ["Chocolate Spread", "Cheese", "Butter"]
// shoppingList는 7개의 아이템을 갖게 된다.
(1) 배열의 값 가져오기
var firstItem = shoppingList[0]
//배열의 0번째 인덱스 값 할당
(2) 배열의 값 변경
shoppingList[0] = "Six eggs"
// 배열의 0번째 인덱스 값 변경
+서브 스크립트 구문을 사용할 때 인덱스는 유효해야 한다.
ex) shoppingList[shoppingList.count] = "Salt"
-> 런타임에러 발생
- insert(_:at:) 메서드 : 배열의 특정 인덱스에 아이템 추가
shoppingList.insert("Maple Syrup", at: 0)
// shoppingList는 7개의 아이템을 포함
// "Maple Syrup"는 배열의 첫번째 아이템
- remove(at:): 배열의 특정 인덱스의 아이템 삭제, 삭제한 아이템 반환
let mapleSyrup = shoppingList.remove(at: 0)
// 0번째 아이템 삭제
// 6개 아이템 존재
// mapleSyrup = "Maple Syrup"
아이템이 삭제되면 배열의 공간도 삭제된다.
+배열의 마지막 아이템을 삭제하고 싶은 경우
- removeLast() 메서드
let apples = shoppingList.removeLast()
// 마지막 아이템 삭제
// 5개의 아이템 존재
// apples = "Apples"
- shuffled() 메서드 : 아이템의 순서가 무작위로 섞인 새로운 배열이 반환
let shuffledTrees = treeArray.Shuffled
- randomElement() 메서드 : 배열의 아이템을 무작위로 선택하여 접근
let randomTree = treeArray.randomElement()
for-in 루프를 사용하여 배열의 전체 값을 알 수 있다.
for item in shoppingList {
print(item)
}
// Six eggs
// Milk
// Flour
// Baking Powder
// Bananas
각 아이템의 인덱스 뿐만 아니라 값도 필요하다면 enumerated() 메서드를 사용한다.
정수와 아이템을 조합하여 튜플로 반환
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의 Any는 특별한 타입으로, 지정된 클래스 타입이 아닌 객체를 참조하는데 사용된다.
Any 객체 타입을 포함하도록 선언된 배열은 여러 타입의 아이템을 담을 수 있게 된다.
let mixedArray: [Any] = ["A String", 432, 34.989]
하지만 Any 타입은 주의해서 사용해야 한다.
Any를 사용할 경우 올바를 타입의 요소들이 배열에 포함되었다고 간주하게 되므로
코드상에서의 프로그래머 실수로 인한 오류가 발생할 수 있기 때문이다.
콜렉션에 순서와 상관없이 같은 타입의 다른 값을 저장하는 데이터 타입
아이템의 순서가 중요하지 않거나 아이템이 반복되면 안될 때 배열 대신 집합 사용
집합에 저장하기 위해 타입은 반드시 hashable이어야 한다.
해쉬 값은 동일하게 비교되는 모든 객체에 대해 동일한 Int 값으로 a == b 이면, a.hashValue == b.hashValue를 따른다.
Swift의 기본 타입은 기본적으로 hashable 이고 집합의 값으로 사용할 수 있다.
var letters = Set<Character>()
print("letters is of type Set<Character> with \(letters.count) items.")
// 출력 : "letters is of type Set<Character> with 0 items."
아래 코드는 String 값을 저장하는 favoriteGenres 라는 집합을 생성한다.
var favoriteGenres: Set<String> = ["Rock", "Classical", "Hip hop"]
// favoriteGenres 3개의 String 타입의 아이템을 가진 집합으로 생성된다.
- favoriteGenres 변수는 Set<String>, **"String 값의 집합"** 으로 선언
- **String 값**만 저장 가능
- favoriteGenres 집합은 3개의 String 값 **("Rock", "Classical", "Hip hop")**으로 초기화
메서드와 프로퍼티로 집합에 접근과 수정할 수 있다.
count 프로퍼티 : 집합의 아이템 갯수print("I have \(favoriteGenres.count) favorite music genres.")
// 출력 "I have 3 favorite music genres."
isEmpty 프로퍼티 : 집합의 count 프로퍼티 값이 0인지 아닌지 판단if favoriteGenres.isEmpty {
// count 프로퍼티 값이 0이면
print("As far as music goes, I'm not picky.")
} else {
// count 프로퍼티 값이 0이 아니면
print("I have particular music preferences.")
}
// 출력 "I have particular music preferences."
- inser(_:) 메서드 : 집합의 특정 인덱스에 아이템 추가
favoriteGenres.insert("Jazz")
// favoriteGenres 집합에 4개의 아이템 존재
- remove(_:) 메서드 : 집합의 특정 인덱스의 아이템 삭제, 삭제한 아이템 반환 / 아이템이 없을 경우 nill 반환
if let removedGenre = favoriteGenres.remove("Rock") {
// 집합에 아이템이 있을 경우 삭제하고 삭제된 값 반환
print("\(removedGenre)? I'm over it.")
} else {
// 해당 아이템이 없을 경우 nil 반환
print("I never much cared for that.")
}
// 출력 "Rock? I'm over it."
- removeAll() 메서드 : 전체 아이템 삭제
- contain(_:) 메서드 : 집합에 특정 아이템이 포함되어 있는지 판단
if favoriteGenres.contains("Funk") {
print("I get up on the good foot.")
} else {
print("It's too funky in here.")
}
// 출력 "It's too funky in here."
for genre in favoriteGenres {
print("\(genre)")
}
// Classical
// Jazz
// Hip hop
swift의 Set 타입은 순서를 가지고 있지 않다.
특정 순서로 집합의 값을 반복하려면
집합의 요소를 <연산자를 사용하여 정렬하여 반환하는 sorted() 메서드 사용
for genre in favoriteGenres.sorted() {
print("\(genre)")
}
// Classical
// Hip hop
// Jazz
- 위는 집합 a, b, c의 관계를 그림으로 나타낸 것
- a 는 b 의 모든 요소를 포함하므로 a 는 b 의 상위집합 (superset)
- b 의 모든 요소가 a 에 포함되어 있으므로 b 는 a 의 부분집합 (subset)
- b 와 c 는 공통 요소가 없으므로 분리집합 (disjoint)
"같음" 연산자 (==) : 두 집합이 같은 값을 모두 포함하고 있는지 판단
isSubset(of:) : 현재 집합이 다른 집합의 부분집합인지 판단
isSuperset(of:) : 현재 집합이 다른 집합의 상위 집합인지 판단
isStrictSubset(of:) / isStrictSuperset(of:) : 집합이 특정 집합과 같지 않고 부분집합인지 상위집합인지 판단
isDisjoint(with:) : 두 집합이 공통 값이 없는지 (분리집합인지) 판단
let houseAnimals: Set = ["🐶", "🐱"]
let farmAnimals: Set = ["🐮", "🐔", "🐑", "🐶", "🐱"]
let cityAnimals: Set = ["🐦", "🐭"]
houseAnimals.isSubset(of: farmAnimals)
//houseAnimal은 farmAnimals의 부분집합이다.
// true
farmAnimals.isSuperset(of: houseAnimals)
//farmAnimals는 houseAnimals의 상위집합이다.
// true
farmAnimals.isDisjoint(with: cityAnimals)
//farmAnimal과 cityAnimals는 분리집합이다.
// true
딕셔너리는 순서와 상관없이 콜렉션에 같은 타입의 키-값 쌍의 형태로 값을 저장한다.
var 변수명: [키 타입: 값 타입] = [키1: 값1, 키2: 값2.....]
var bookDict = ["100" : "wind in the willows",
"202" : "Shutter Island",
"104" : "Sense and Sensibility"]
빈 Dictionary 생성
var namesOfIntegers = [Int: String]()
// namesOfIntegers는 [Int: String] 타입의 비어있는 dictionary
키는 Int타입, 값을 String 타입
키들과 값들을 Swift의 zip() 함수에 전달하면 된다.
let keys = ["100", "202", "104"]
let values = ["wind in the willows", "Shutter Island", "Sense and Sensibility"]
let bookDict = Dictionary(uniqueKeysWithValues: zip(keys, values))
위의 방법은 키들과 값들을 프로그램적으로 생성되게 해준다.
키들을 미리 정의된 배열로 이용하는 것이 아니라 1부터 시작하는 숫자로 설정할 수 있다.
let values = ["wind in the willows", "Shutter Island", "Sense and Sensibility"]
let bookDict = Dictionary(uniqueKeysWithValues: zip(1..., values))
var bookDict = [1 : "wind in the willows",
2 : "Shutter Island",
3 : "Sense and Sensibility"]
count 프로퍼티 : 딕셔너리의 아이템 갯수print("The airports dictionary contains \(airports.count) items.")
// 출력 : "The airports dictionary contains 2 items."
isEmpty 프로퍼티 : 딕셔너리의 count 프로퍼티 값이 0인지 아닌지 판단if airports.isEmpty {
print("The airports dictionary is empty.")
} else {
print("The airports dictionary is not empty.")
}
// 출력 : "The airports dictionary is not empty."
(1) 새로운 아이템 추가
적절한 키의 타입을 서브 스크립트 인덱스로 사용하고 적절한 값의 타입을 할당
airports["LHR"] = "London"
// 키 "LHR", 값 "London 추가
(2) 값 변경
특정 키를 서브 스크립트 구문으로 사용
airports["LHR"] = "London Heathrow"
// 키 "LHR"의 값을 "London" -> "London Heathrow" 으로 변경
(3) 특정 키로 딕셔너리 값 가져올 때
옵셔널 값 을 반환nil 을 반환if let airportName = airports["DUB"] {
//키의 값이 있는 경우, 옵셔널 값 반환
print("The name of the airport is \(airportName).")
} else {
//키의 값이 없는 경우, nil 반환
print("That airport is not in the airports dictionary.")
}
// 출력 : "The name of the airport is Dublin Airport."
if let oldValue = airports.updateValue("Dublin Airport", forKey: "DUB") {
print("The old value for DUB was \(oldValue).")
}
// 출력 : "The old value for DUB was Dublin."
삭제된 값을 반환nil 을 반환if let removedValue = airports.removeValue(forKey: "DUB") {
print("The removed airport's name is \(removedValue).")
} else {
print("The airports dictionary does not contain a value for DUB.")
}
// Prints "The removed airport's name is Dublin Airport."
딕셔너리의 각 아이템은 (key, value) 튜플로 반환되고 튜플의 멤버를 임시 상수(변수)로 분리할 수 있다.
for (airportCode, airportName) in airports {
//튜플로 반환
print("\(airportCode): \(airportName)")
}
// LHR: London Heathrow
// YYZ: Toronto Pearson
// 키 : 값
딕셔너리의 키 또는 값에 반복 가능한 콜렉션을 가져올 수도 있다.
//keys 프로퍼티
for airportCode in airports.keys {
print("Airport code: \(airportCode)")
}
// Airport code: LHR
// Airport code: YYZ
//values 프로퍼티
for airportName in airports.values {
print("Airport name: \(airportName)")
}
// Airport name: London Heathrow
// Airport name: Toronto Pearson
딕셔너리의 키 또는 값을 Array 인스턴스의 API로 사용해야 할 경우
keys values 프로퍼티로 새로운 배열을 초기화 하면 된다.
let airportCodes = [String](airports.keys)
// airportCodes is ["LHR", "YYZ"]
let airportNames = [String](airports.values)
// airportNames is ["London Heathrow", "Toronto Pearson"]