KWiOS
KWiOS0101
KWiOS
  • 분류 전체보기 (108)
    • Algorithm (41)
      • 이코테 (14)
      • 이코테 문제풀이 (21)
      • 프로그래머스 (6)
    • CS (1)
      • 모두를 위한 컴퓨터 과학(CS50 2019) (0)
    • iOS (15)
    • Swift (36)
      • Swift문법 (32)
      • 기타 (4)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 6

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
KWiOS

KWiOS0101

Swift/Swift문법

Swift문법 - Collection

2023. 2. 26. 17:05

Swift는 Array, Dictionary, Set 3가지 컬렉션을 제공한다.

Array - 배열을 순서대로 저장

Dictionary - [Key: Value]로 저장

Set - 집합 연산을 제공

 

Array

data를 순서대로 저장하는 컬렉션으로 동일한 자료형의 객체만 저장할 수 있다.

각각의 요소에 접근할때는 인덱스로 접근하며 컬렉션 내부의 하나의 요소를 element라고 한다.

// 기본 문법 
Array<T>
let strArray = Array<String>

// 단축 문법 
[T]
let strArray = [String]

 

배열 생성하기 

let nums = [1,2,3,4]
let emptyArray: [Int] = [] 

// 정식 문법
let emptyArray2 = Array<Int>()

// 단축 문법
let emptyArray3 = [Int]()

// 0이 10번 채워진 Int배열
let zeroArray = [Int](repeating: 0, count: 10)

 

 

배열 검사하기 

// 배열 요소의 갯수를 통해 빈 배열인지 확인하는 방법
nums.count == 0 
// .isEmpty() 메소드를 통해 빈 배열인지 확인하는 방법
nums.isEmpty

 

배열 접근하기

let fruitsArray = ["Apple", "Banana", "Melon"]

fruitsArray[0] // "Apple"
fruitsArray[2] // "Melon"

fruitsArray[0...1]
subscript문법을 통해 범위 인덱스를 지정할 수 있으나, 올바른 인덱스에 접근하지 않은 경우 오류가 발생할 수 있어 주의해야한다.
// 첫번째 인덱스
fruitsArray[fruits.startIndex]

// 마지막 인덱스
// endIndex는 마지막 인덱스의 다음 인덱스를 의미한다.
fruitsArray[fruits.endIndex]

// 마지막 인덱스 구하는 방법 
fruitsArray[fruits.index(before: fruits.endIndex)]
fruitsArray.first
fruitsArray.last 

print(fruitsArray.first) // "Optional("Apple")\n"
print(fruitsArray.last) // "Optional("Melon")\n"

// fruitsArray.first fruitsArray.last는 옵셔널이기때문반환할 값이 없다면 nil을 반환한다.

 

배열 요소 추가하기

var alphabet = ["A", "B", "C"]

// 배열 마지막에 요소 추가
alphabet.append("E") // ["A", "B", "C", "E"]
//alphabet.append(1)
alphabet.append(contentsOf: ["E", "F"]) // ["A", "B", "C", "E", "E", "F"]
alphabet.append(1)은 에러가 발생한다. alphabet배열은 String 타입으로 추론되어있어 String 타입만 추가할 수 있다. 
append(contentsOf:) 메소드로 한개가 아닌 여러개의 요소를 추가할 수 있다.
// 배열 중간에 요소 추가
alphabet.insert("d", at: 3) // ["A", "B", "C", "d", "E", "E", "F"]
alphabet.insert(contentsOf: ["a", "b", "c"], at: 0) // ["a", "b", "c", "A", "B", "C", "d", "E", "E", "F"]
append 메소드로 요소를 추가 할 경우 오버헤드가 발생하지 않고,
insert 메소드로 요소를 추가 할 경우 기존 요소들이 뒤로 밀리기때문에 오버헤드가 발생한다.
// 배열 요소를 다른 요소로 변경
alphabet[0...2] = ["x", "y", "z"] // ["x", "y", "z"]
alphabet // ["x", "y", "z", "A", "B", "C", "d", "E", "E", "F"]

// 메소드를 이용해서 배열요소를 다른 요소로 변경
alphabet.replaceSubrange(0...2, with: ["a", "b", "c"]) // ["a", "b", "c", "A", "B", "C", "d", "D", "E", "F"]
// 빈 배열로 해당 범위의 요소를 삭제
alphabet[0..<1] = []
alphabet // ["A", "B", "C", "d", "D", "E", "F"]

 

배열 요소 삭제하기

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) // ["E", "F", "G"]
alphabet // ["E", "F", "G"]

// 전체 배열의 요소 삭제
alphabet.removeAll() 

// 마지막 요소 삭제
alphabet = ["A", "B", "C", "D", "E", "F", "G"]
alphabet.removeLast() // "G"
alphabet // ["A", "B", "C", "D", "E", "F"]
alphabet배열이 빈배열이라면 .removeLast 메소드는 String타입을 반환하기 때문에 에러가 발생한다.
// 마지막 요소 삭제
alphabet.popLast()
.removeLast() .popLast() 두가지 모두 마지막 요소를 삭제하는 메소드인데
.removeLast()의 경우 리턴값이 String이고 
.popLast()은 String? 이므로 빈배열이라면 에러가 아닌 nil이 리턴되기 때문에 .popLast()가 좀더 안전하다.
//범위 지정 후 요소 삭제
alphabet = ["A", "B", "C", "D", "E", "F", "G"]
alphabet.removeSubrange(0...2) // ["D", "E", "F", "G"]
alphabet // ["D", "E", "F", "G"]

 

배열 요소 비교하기

let a = ["A", "B", "C"]
let b = ["a", "b", "c"]


// 비교 연산자를 통해서 비교
a == b
a != b
a.elementsEqual(b) 


// 대소문자를 구분하지 않고 비교
a.elementsEqual(b) { (lhs, rhs) -> Bool in
    return lhs.caseInsensitiveCompare(rhs) == .orderedSame
}

 

배열 요소 찾기

let nums = [1,8,2,3,4,5,6,7,8,9]
nums.contains(3)
nums.contains(9)

// 짝수가 존재하는지 검색
nums.contains { (n) -> Bool in
    return n.isMultiple(of: 2) // true
}

// 가장먼저 검색된 짝수 검색
nums.first { (n) -> Bool in
    return n.isMultiple(of: 2) // 8
}

// 가장 먼저 검색된 짝수의 인덱스 검색
nums.firstIndex { (n) -> Bool in
    return n.isMultiple(of: 2) // 1
}

 

배열 요소 정렬하기

let nums = [1,3,2,4,6,5,8,9,7]

// 오름차순
nums.sorted()

// 내림차순
nums.sorted().reversed() // ReversedCollection<Array<Int>>
[Int](nums.sorted().reversed()) // [9, 8, 7, 6, 5, 4, 3, 2, 1]
.reversed는 원본 메모리를 공유하므로 생성자를 이용해서 새로운 메모리에 할당해주어야 한다.
// 배열 요소 스왑하기
var swapNums = nums
swapNums.swapAt(0, 1) // [3, 1, 2, 4, 6, 5, 8, 9, 7]

// 배열 요소 섞기
swapNums.shuffle() // [4, 2, 3, 6, 1, 5, 7, 9, 8]

 


Dictionary

사전과 유사한 형태로 데이터를 저장하는 컬렉션으로 [Key: Value]형식으로 저장된다. 

dictionary는 정렬되어 있지 않으며 배열과같이 자료형이 같아야 저장할 수 있다.

// 기본 문법
[key: value, key: value]

// 정식 문법으로 선언 
let emptyDict3 = Dictionary<String,String>()

// 단축 문법으로 선언
let emptyDict2 = [String: String]()

 

딕셔너리 생성하기 

// 요소가 있는 Dictionary
let a = ["a" : "apple", "b" : "banana"]

// 빈 Dictionary
let emptyDict: [String:String] = [:]

 

딕셔너리 검사하기

// 저장되어있는 요소 수 확인
a.count == 0

// 비어있는지 확인
a.isEmpty

 

딕셔너리 접근하기 

딕셔너리는 Key를 통해 접근할 수 있으며 Value를 통해서는 접근할 수 없다.

딕셔너리는 순서없이 쌍으로 저장된 컬렉션이므로 정렬된 형태로 저데이터를 얻으려면 따로 정렬해야 한다.

a["A"] // key를 전달하면 해당 key의 value를 반환
a["Apple"] // 해당하는 key가 없다면 nil을 반환

 

딕셔너리 정렬하기 

// 키값 정렬하기
for k in word.keys.sorted() {
    print(k) // 
}

// 벨류값 정렬하기
for v in word.values.sorted() {
    print(v) // 
}

// 키값 배열에 저장하기
let keys = Array(word.keys) // ["A", "B", "C"]

// 벨류값 배열에 저장하기
let values = Array(word.values) // ["Apple", "Banana", "City"]

 

딕셔너리 요소 추가하기 

딕셔너리에 새로운 값을 추가할 때는 Key를 통해서 추가할 수 있다.

var words = [String : String]()

words["A"] = "apple"
words["B"] = "banana"

words.count // 2
words // ["B": "banana", "A": "apple"]

words["B"] = "melon"

// 키가 존재하지 않는다면 새로운 값을 추가하고 키가 존재한다면 해당 키의 값을 변경한다.
//updateValue() 메소드로 값 추가/변경하기
words.updateValue("city", forKey: "C")
words.updateValue("banana", forKey: "B")
words // ["B": "banana", "A": "apple", "C": "city"]

 

딕셔너리 요소 삭제하기 

words["B"] = nil 
words // ["C": "Circle", "A": "Apple"]
// 지우고싶은 키에 nil을 할당하면 해당 키는 삭제된다. 

words["Z"] = nil
// 존재하지 않는 키를 삭제하면 아무런 오류 없이 다음 줄의 코드가 실행된다.
// 메소드를 사용하여 삭제
words.removeValue(forKey: "A") 
// key와 한 쌍인 value를 삭제한 다음 삭제된 value를 반환한다.
words.removeValue(forKey: "A") 
// 삭제할 값이 없으므로 nil을 반환한다.

// 전체 dictionary를 삭제
words.removeAll()
words // [:] 빈 딕셔너리

 

딕셔너리 비교하기 

딕셔너리는 정렬되어있지 않기 때문에 정렬하고 값을 비교해야 한다.

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

let akeys = a.keys.sorted()
let bkeys = b.keys.sorted()

akeys.elementsEqual(bkeys) { (lhs, rhs) -> Bool in
    guard lhs.caseInsensitiveCompare(rhs) == .orderedSame else {
        return false
    }

    guard let lv = a[lhs], let rv = b[rhs], lv.caseInsensitiveCompare(rv) == .orderedSame else {
        return false
    }
    return true
}
위 소스를 보면 먼저 akeys.elementsEqual(bkeys)로 정렬된 키값이 같은지 확인한다. 정렬된 키값이 같다면 두번째 가드문으로 키를 통해서 두 값을 가져오고 그 값이 같은지 비교한다.

 


Set

배열처럼 하나의 데이터를 하나의 요소로 저장하며 정렬 순서보다 검색 속도가 중요한 경우 배열 대신에 사용하기도 한다. 

딕셔너리처럼 정렬되어 있지 않고 배열처럼 인덱스를 사용하지 않는다. 

hashing 알고리즘을 사용하기 때문에 배열보다 검색속도가 빠르고 중복된 값을 저장하지 않으며 집합연산에 특화되어 있다. 

 

Set 생성하기

// 기본 문법
var strs = Set<String>()
// 주의할 점 

let Set = [1,2,3,4,5,6]
Set.count // 6
// 배열로 인식한다. Set은 형식추론 불가능하다.

let set: Set<Int> = [1,2,2,3,3,4,5,6,6]
set.count // 6
// set은 중복된 값을 하나로 인식한다.

 

Set 검사하기

let set: Set = [1,2,2,3,3,3]
// 저장된 요소 갯수 확인
set.count // 3

// 비어있는지 확인
set.isEmpty // false

 

Set 요소 추가하기

var words = Set<String>()

var insertResult = words.insert("Swift") 
// insert 메소드는 튜플 형식(insertResult: , memberAfterInsert: )으로 값을 반환한다. 

insertResult.inserted // true
insertResult.memberAfterInsert // "Swift"

insertResult = words.insert("Swift")
// Set은 동일한 값을 저장하지 않으므로 false가 반환된다.

insertResult.inserted // false
insertResult.memberAfterInsert // "Swift"
var updateResult = words.update(with: "Swift")
updateResult // "Swift"

updateResult = words.update(with: "Apple")
updateResult // nil
update() 메소드는 insert + update = upsert 방식으로 값을 저장한다.
새로운 문자열을 추가했을때 nil이 반환되면 insert이고 문자열이 리턴된다면 update이다.

 

Set 요소 삭제하기

// 해당 요소를 삭제
words.remove("Swift") // "Swift"
words.remove("AAA") // nil. 존재하지 않는 값을 반환

// 전체 요소를 삭제
words.removeAll()

 

Set 요소 비교하기

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]
let d: Set = [1, 7, 5, 9, 3]

a.elementsEqual(d) // 항상 결과가 다르게 나온다.
set은 정렬되지 않았기 때문에 .elementsEqual 메소드를 사용할때 조심해야한다. 안전한 방법은 먼저 set을 Array로 바꾸고 배열을 같은 기준으로 정렬해서 비교해야 안전하다.

 

Set 집합 연산 

  1. a.union(b) -> 합집합
  2. a.intersection(b) -> 교집합
  3. a.subtracting(b) -> 차집합
  4. a.symmetricDifference(b) -> 여집합

'Swift > Swift문법' 카테고리의 다른 글

Swift문법 - Struct and Class  (0) 2023.03.12
Swift문법 - Enumeration  (0) 2023.03.05
Swift문법 - String Options  (0) 2023.02.19
Swift문법 - String and Characters  (0) 2023.02.12
Swift문법 - Tuples  (0) 2023.02.05
    'Swift/Swift문법' 카테고리의 다른 글
    • Swift문법 - Struct and Class
    • Swift문법 - Enumeration
    • Swift문법 - String Options
    • Swift문법 - String and Characters
    KWiOS
    KWiOS

    티스토리툴바