Programming/Swift(iOS)

Swift Generic - 3

홍열 2021. 4. 6. 21:28
728x90

String 배열의 빈도수를 세는 프로그램을 짜 봅시다. 

 

hash로 빈도수를 세면 될것 같은데요..(python이면 collections의 defaultdict를 사용하겠지만..)

let arr = [
  "hello",
  "world",
  "hello",
  "world",
  "hello",
  "world",
  "show",
  "me",
]

func printValues(_ values: [String]) {
  print(values.sorted())
  var result = [String: Int]()
  for e in values {
  	//result[e]가 존재하지 않으면 0, 존재하면 값 가져오는 부분 
    let v = result[e] ?? 0
    result[e] = v + 1
  }
  print(result)
}

 

만약 String이 아니라 다른게 들어오면 제너릭으로 어떻게 구현해야될까요?

 

객체가 비교 가능해야되니까 "Comparable" protocol은 준수해야될것 같고..

hash 값을 써야되니까 "Hashable" protocol을 추가적으로 준수해야 될 것 같습니다. 

 

두개의 Protocol을 준수하려면 어떻게 해야될까요?

Comparable & Hashable  두개로 연결하면 됩니다. 

 

// 제약 사항이 여러 개 존재할 경우,
//  1) <T: Comparable & Hashable>
//  2) where T: Comparable & Hashable

func printValues<T: Comparable & Hashable>(_ values: [T]) {
  print(values.sorted())  // Comparable
  var result = [T: Int]() // Hashable
  for e in values {
    let v = result[e] ?? 0
    result[e] = v + 1
  }
  print(result)
}

func printValues<T>(_ values: [T]) where T: Comparable & Hashable
{
  print(values.sorted()) // Comparable
  var result = [T: Int]() // Hashable
  for e in values {
    let v = result[e] ?? 0
    result[e] = v + 1
  }

  print(result)
}

let arr = [
  "hello",
  "world",
  "hello",
  "world",
  "hello",
  "world",
  "show",
  "me",
]
printValues(arr)

 

이번에는 사용자가 만든 객체 타입의 빈도수를 세려면 어떻게 해야될까요?

마찬가지로 "Comparable"과 "Hashable"의 Protocol을 준수하면 됩니다. 

struct User {
  let name: String // Hashable / Equtable
  let age: Int     // Hashable / Equtable
}

extension User : Comparable {
  static func < (lhs: User, rhs: User) -> Bool {
    return lhs.name < rhs.name
  }
}

extension User : Hashable {
    //Equatable
    static func ==(lhs:User, rhs:User) -> Bool {
        return lhs.name == rhs.name && lhs.age == rhs.age
    }
    //Hashable
    func hash(into hasher: inout Hasher) {
        hasher.combine(name)
        hasher.combine(age)
    }
}


let arr2 = [
  User(name: "Tom", age: 42),
  User(name: "Bob", age: 100),
  User(name: "Tom", age: 42),
  User(name: "Bob", age: 100),
  User(name: "Tom", age: 42),
  User(name: "Bob", age: 100),
  User(name: "Tom", age: 42),
  User(name: "Bob", age: 100),
]
printValues(arr2)

Swift의 구조체의 프로퍼티가 Hashable / Equtable에 대한 프로토콜을 만족한다면,  별도의 구현을 제공할 필요가 없습니다