Swift Collection Type

최준영·2022년 6월 6일
1

Swift

목록 보기
2/6
post-custom-banner

컬렉션 공통매서드

.isEmpty //컬레션이 비었는지 확인
.count //컬렌션에 들어있는 요소 개수

Array

Create

var arr1: Array<String> = ["jun", "yoeng", "choi"];
print(arr1); //["jun", "yoeng", "choi"]

var arr2: [String] = ["jun", "yoeng", "choi"];
print(arr2); //["jun", "yoeng", "choi"]

var arr3: [Any] = [];
print(arr3.isEmpty, arr3.count, arr3); //true 0 []

배열의 크기 지정선언

  • Array.init(reapeating:count:) 이니셜라이저를 사용하여 선언이 가능하다.
var arr = Array.init(repeating: "초기화값", count: 5)
print(arr) 
["초기화값", "초기화값", "초기화값", "초기화값", "초기화값"]

Read

var names: [String] = ["junyeong", "changhoon", "minjae"];
print(names[0], names[1], names[2]); //junyeong changhoon minjae
print(names.first, names.last); //Optional("junyeong") Optional("minjae")

💡이름으로 인스턴스 인덱스 찾기

//앞에서부터 찾아서 가장 먼저발견한 인덱스
print(names.firstIndex(of: "junyeong")) //Optional(0) 
names.append("junyeong");
//뒤에서부터 찾아서 가장 먼저발견한 인덱스
print(names.lastIndex(of: "junyeong")) //Optional(3)

Update

var countries: [String] = [];
countries.append("Kor");

print(countries); //["Kor"]

//추가하고싶은 인스턴스가 많을경우 'contentsOf'인수에 배열로 전달하면 된다,

countries.append(contentsOf: ["America", "Japan", "China"]);

print(countries); //["Kor", "America", "Japan", "China"]

var numbers: [Int] = [1,4,5];
//at인수에는 인덱스를 전달한다, 기존에 요소는 뒤로밀린다.
numbers.insert(contentsOf: [2,3], at: 1); 
print(numbers); //[1, 2, 3, 4, 5]

Delete

numbers.remove(at: 4) //at에 인덱스를 전달하면 해당 인덱스 요소를 삭제하고 반환한다
print(numbers) //[1, 2, 3, 4]
numbers.removeFirst(); //마찬가지로 삭제되는 요소를 반환
numbers.removeLast();
print(numbers); //[2, 3]
  • 범위연산자 사용예시
print(numbers[0...2]) //[1, 2, 3]
numbers[0...4] = [5,4,3,2,1];
print(numbers); //[5, 4, 3, 2, 1]

Iterable

배열의 요소 순회

  • 범위연산자를 활용해 index로 배열요소에 접근할 수 있다.
for i in 0..<array.count {
    print(arr[i])
}
  • 배열을 집적넣어줘 요소를 순회할 수 있다.
for element in arr {
    print("element: \(element)")
}
  • indices나 enumerated 매서드를 활용하여 index에 접근이 가능하다.
for index in arr.indices {
    print("index: \(index)")
}

for (index, element) in arr.enumerated() {
    print("index: \(index), element: \(element)")
}
  • foreach문은 클로저를 매개변수로 전달받아 클로저에게 요소를 전달한다.
arr.forEach({
    print($0)
})

Dictionary

  • Key : Value 형태의 집합이다.

Create

//키의 이름은 중복불가 == 유일한 식별자
//데이터타입에 ','가 중간에 들어가는 것 주의!! 
var dic1: Dictionary<String, Int> = ["jun" : 1, "chang" : 2];
print(dic1); //["chang": 2, "jun": 1]
//축약
var dic2 :[String:Int] = ["dong" : 3];
print(dic2) //["dong": 3]

//[String:Int]는 딕셔너리 축약 타입임으로 별칭화 가능하다.
typealias stringIntDic = [String: Int];
var dic3: stringIntDic = stringIntDic();
print(dic3)//[:]
  • Any타입을 활용한 딕셔너리
    key, value 타입을 자유롭게 사용가능하다.
var dic: [String: Any] = ["name" : "choi", "age" : 23]

guard let name=dic["name"] as? String else {
    fatalError()
}

guard let age=dic["age"] as? Int else {
    fatalError()
}

print("이름: \(name), 나이: \(age)")

Read

var dic4: stringIntDic = ["jun":98];

print(dic4["jun"]); //Optional(98)

//만약 키의 존재여부를 모를때 'default: 값'을 함께적으면 키를 찾지못했을 때 값이 반환된다.
print(dic4["dong", default: 404]); //404

Update

typealias stringIntDic = [String : Int] 

//생성
var dic5: stringIntDic = stringIntDic();
dic5["jun"] = 98;
dic5["chang"] = 84;
print(dic5); //["jun": 98, "chang": 84]
//업데이트
dic5["jun"] = 123;
print(dic5); //["jun": 123, "chang": 84]

Delete

var dic6: [String:Int] = ["a" : 26, "b" : 27];
dic6.removeValue(forKey: "a");
print(dic6); //["b": 27]

Extra

딕셔너리의 키가 되려면 Hashable 프로콜을 채택해하는 타입이어야 한다.
스위프트의 기본 타입들(String, Int ..)들은 모두 이 프로토콜을 채택한다.
하지만 구조체나 클래스, 열거형을 키로 사용할 수 없을까?

위 에러를 보면 구조체가 Hashable 프로토콜을 conform(순응하다, 따르다)하지 않는다고 말한다.

struct StructKey: Hashable {
    var prop1:String
    var prop2:Int
}

var dic1:[StructKey:Int]=Dictionary()

let key=StructKey(prop1: "choi", prop2: 23)

dic1[key]=100

print(dic1[key]!) //100

하지만 Hashable 프로토콜을 채택하면 위와같이 key로 사용이 가능하다.
하지만 여기서도 조건이 있다.
구조체의 프로퍼티 역시 모두 Hashable프로토콜을 채택해야 한다는 점이다.

하지만 클래스의 경우 Hashable 프로토콜을 채택하는 것만으로는 key값으로 사용할 수 없다.

class ClassKey: Hashable {
    var prop1:String
    var prop2:Int
    init(prop1:String, prop2:Int){
        self.prop1=prop1
        self.prop2=prop2
    }
    
    func hash(into hasher: inout Hasher) {
        hasher.combine(prop1)
        hasher.combine(prop2)
    }
    
    static func == (lhs:ClassKey, rhs:ClassKey)->Bool{
        return lhs.prop1==rhs.prop1 && lhs.prop2==rhs.prop2
    }
    
}

var dic1:[ClassKey:Int]=Dictionary()

let key=ClassKey(prop1: "choi", prop2: 23)

dic1[key]=100

print(dic1[key]!) //100

위 코드처럼 hash함수와 ==연산자를 직접 구현해 주어야 한다.
hasher.combine의 전달인자는 모둔 Hashable 프로토콜을 채택해야한다.


Set

  1. 순서가 중요하지 않은 유일한값들의 집합이다.

Create

//다른 컬렉션타입들과 다르게 Set는 축약표현이 없다.
var student: Set<String> = ["choi", "lee", "kim"];
print(student); //["lee", "kim", "choi"]

var elite: Set<String> = ["choi", "lee", "han"];

//교집합(A ∩ B)
var intersection: Set<String> = student.intersection(elite);
print(intersection); //["lee", "choi"]

//여집합의 합(A ∪ B - A ∩ B))
var symmetricDiffSet: Set<String> = student.symmetricDifference(elite);
print(symmetricDiffSet); //["han", "kim"]

//합집합(A ∪ B)
var union: Set<String> = student.union(elite);

//차집합(A - B)
var subtracting: Set<String> = student.subtracting(elite);

print("교집합: \(union), 차집합: \(subtracting)") 
//교집합: ["lee", "kim", "han", "choi"], 차집합: ["kim"]

Read

//Set은 순서가 의미가없어 인덱스로 값을 읽지 못한다
let foodSet: Set<String> = ["chicken", "bugger", "americano"];
print(foodSet, "type: \(type(of: foodSet))") 
//["americano", "chicken", "bugger"] type: Set<String>

//sorted매서드를 이용하면 Set을 정렬된 배열로 바꿔 반환한다.(Set은 변하지 않는다) 
let foodArray: [String] = foodSet.sorted();
print(foodArray, "type: \(type(of: foodArray))") 
//["americano", "bugger", "chicken"] type: Array<String>

Update

var foodSet: Set<String> = ["chicken", "bugger", "americano"];
foodSet.insert("cake");

print(foodSet); //["bugger", "americano", "cake", "chicken"]

Delete

var foodSet: Set<String> = ["chicken", "bugger", "americano"];
foodSet.remove("bugger"); //contentsOf 인수가 사용되지 않는다.

print(foodSet); //["americano", "chicken"]

Enum

  1. 열거형은 연관된 항목들을 묶어서 표현할 수 있는 타입이다.
  2. 처음지정된 항목값을 추가/수정이 불가능하다.
  3. 열거형 항목의 이름이 곧 고유의 값이다. (내부적으로 치환되지 않음)
  4. 항목자체도 고유값이지만 항목의 원시 값(Raw Value)도 가질 수 있다.

Create/Read

//일반형 
enum menu {
    case pasta
    case pizza
    case juice
}

//축약
enum menu2 { case pasta, pizza, juice}

//각 항목은 지정값을 가질 수 있다.
//항목에 원시값을 주지않는 경우 String은 항목이름이 부여된다.
//Int는 0부터 오름차순으로 부여된다.
enum menu3: String {
    case pasta = "로제"
    case pizza = "마르게리타"
    case juice
}
print(menu3.juice.rawValue, type(of: menu3.juice.rawValue)); //juice String

var food: menu3 = .pasta; //열거형 이름 생략가능
print(food, food.rawValue); //pasta 로제

//원시값의 타입을 항목마다 다르게 부여할 수 있다.
enum menu4 {
    case pasta(flavor: String)
    case pizza(dough: String, size: Int)
    case juice(String) //타입만 적어도됨
}

var food2: menu4 = .pasta(flavor: "rose"); 
print(food2) //pasta(flavor: "rose")

var food3: menu4 = .juice("grape");
print(food3) //juice("grape")
  • 열거형에대해서는 추후에 더깊은 내용을 포스팅하겠다.

profile
Developer가 되고싶은 꿈나무
post-custom-banner

0개의 댓글