[프로그래머스] 베스트앨범 Swift
https://school.programmers.co.kr/learn/courses/30/lessons/42579?language=swift
내 코드
import Foundation
struct Record {
let name: String
let count: Int
let index: Int
}
func map(_ genres: [String], _ plays: [Int]) -> [Record] {
var records: [Record] = []
for i in 0..<genres.count {
records.append(Record(name: genres[i], count: plays[i], index: i))
}
return records
}
func getGenrePlayCount(_ record: [Record], _ genre: Set<String>) -> [(String, Int)] {
var genrePlayCount: [String: Int] = [:]
for r in record {
genrePlayCount[r.name, default: 0] += r.count
}
return genrePlayCount.sorted { $0.value > $1.value }
}
func solution(_ genres: [String], _ plays: [Int]) -> [Int] {
let genre = Set(genres)
let record = map(genres, plays)
let specificGenre = getGenrePlayCount(record, genre)
var result: [Int] = []
for (genreName, _) in specificGenre {
let filterList = record.filter { $0.name == genreName }.sorted { $0.count > $1.count }
// prefix(2) 보다 시간 복잡도가 더 낮았다 (프로그래머스 환경 에서는)
// 기존 조건문을 변경하고 싶어서 아래 처럼 변경
// 기존 방식과 거의 유사하지만, `prefix(2)`의 사용을 피하며 코드 간결화
for i in 0..<min(2, filterList.count) {
result.append(filterList[i].index)
}
}
return result
}
Review
처음 문제를 봤을 때 해야 할 것은 "장르별로 가장 많이 재생된 노래를 두개씩 모아 고유 번호가 들어 있는 하나의 리스트로 반환해주는 것"
이라고 생각 하였습니다.
저는 장르(name)와 재생 횟수(count) 고유번호(index)를 구분하기 위해 Record 객체를 만들어 주었습니다.
func map(_ genres: [String], _ plays: [Int]) -> [Record] {
var records: [Record] = []
for i in 0..<genres.count {
records.append(Record(name: genres[i], count: plays[i], index: i))
}
return records
}
map 함수는 예제에서 제공한 데이터를 제가 원하는 Record 데이터로 변환해 주는 함수입니다.
예를 들어 위 예제에서 나온 genres로 만든다면 Record(name: "classic", count: 500, index: 0) 이런 데이터를 리스트에 넣어 준다고 생각하면 됩니다.
그렇게 만들어진 Record 배열은 getGenrePlayCount 라는 함수에 사용이 됩니다.
func getGenrePlayCount(_ record: [Record], _ genre: Set<String>) -> [(String, Int)] {
var genrePlayCount: [String: Int] = [:]
for r in record {
genrePlayCount[r.name, default: 0] += r.count
}
return genrePlayCount.sorted { $0.value > $1.value }
}
getGenrePlayCount 함수는 Record 배열에서 장르와, 장르의 총 재생 횟수를 튜플로 만들어 주는 함수입니다.
딕셔너리를 튜플로 변환해 준 이유는 총 재생 횟수 순으로 정렬을 하기 위함입니다.
그러면 getGenrePlayCount 함수는 [("pop", 3100), ("classic", 1450)] 이런 형태로 리턴 이 됩니다.
func solution(_ genres: [String], _ plays: [Int]) -> [Int] {
let genre = Set(genres)
let record = map(genres, plays)
let specificGenre = getGenrePlayCount(record, genre)
var result: [Int] = []
for (genreName, _) in specificGenre {
let filterList = record.filter { $0.name == genreName }.sorted { $0.count > $1.count }
for i in 0..<min(2, filterList.count) {
result.append(filterList[i].index)
}
}
return result
}
따라서 마지막 solution 함수에서
1. getGenrePlayCount 함수를 호출하여 받은 결과 값으로 장르 이름만 가져와서
2. Record 배열에서 genreName 과 같은 거를 거르고 각각 재생 횟수별로 정렬합니다.
3. 마지막으로 최대 2개를 result 배열에 노래의 고유번호를 넣어주는 방법으로 구현을 하였습니다. ( 1개 일 때는 1개만 )