간단한 문제 요약
(photo)사진들 속에 있는 (name)특정 인물들은 (yearning)그리움 점수가 있습니다. 각각의 사진이 주어질 때 사진 속에 특정 인물들의 그리움 점수를 합산 한 값을 배열로 완성해주세요.
문제 풀이
photo에서 각각의 배열에는 특정 사진 속 인물들의 이름이 있습니다. photo.map을 사용해서 각각의 사진속 특정 인물들의 배열을 얻어온 후에 그 특정 사진의 인물들이 name에 존재하는가? firstIndex(of:)함수를 통해 index가 반환된다면 yearning 그리움이 값을 더해가며 사진 속 그리움 값을 계산해 나갔습니다.
func solution( _ name:[String], _ yearning:[Int], _ photo:[[String]]) -> [Int] {
return photo.map {
$0.reduce(0) {
guard let idx = name.firstIndex(of: $1) else { return $0 }
return $0 + yearning[idx]
}
}
}
코드 개선점을 찾다 다른 분의 코드를 봤는데 딕셔너리를 써도 좋았을 것 같다는 생각을 했습니다.
func solution(_ name:[String], _ yearning:[Int], _ photo:[[String]]) -> [Int] {
let score: [String: Int] = Dictionary(uniqueKeysWithValues: zip(name, yearning))
return photo.map { $0.reduce(0) { $0 + (score[$1] ?? 0) } }
}
//honghoker님 코드
Dictionary의 init(uniqueKeysWithValues:) 는 주어진 keysAndValues를 통해 key-value pair를 만들어서 저장합니다.
이때 S는 sequence여야 하고, sequence 각각의 Element는 (Key,Value) 타입이어야 합니다. 이는 zip(_:_:) 함수를 통해 연속적인 두개의 sequence를 위에서 만족하는 S 타입으로 만들 수 있습니다. 그래서 name과 yearning을 (Key,Value) 타입으로 하는 sequence로 만들 수 있고 이를 Dictionary로 생성할 수 있습니다.
굳이 왜 딕셔너리를 만들까? 할 수도 있지만,
딕셔너리의 subscript(key:)를 통해 딕셔너리 내 존재하는 key가 아닐 경우 옵셔널을 반환할 수 있고, 이는 위에서 제가 사용했던 firstIndex(of:)를 대체할 수 있습니다. +_+
photo내 특정 인물들이 존재하지 않을 경우 key(name에 이름 존재 x)가 존재하지 않기 때문에 옵셔널 타입을 반환합니다. 이는 0으로 ?? 연산자 swift nil-coalescing operator로 변환할 수 있습니다.