본문 바로가기

ALGORITHM

[Swift] 베스트앨범 (dictionary, 정렬)

https://programmers.co.kr/learn/courses/30/lessons/42579#

 

코딩테스트 연습 - 베스트앨범

스트리밍 사이트에서 장르 별로 가장 많이 재생된 노래를 두 개씩 모아 베스트 앨범을 출시하려 합니다. 노래는 고유 번호로 구분하며, 노래를 수록하는 기준은 다음과 같습니다. 속한 노래가

programmers.co.kr

생각

dictionary 에

key : 장르이름

value : (고유번호, 재생된 횟수)

로 선언해서 넣는다.

 

[정렬]

1. 재생된 횟수를 모두 더해서 비교하여 재생된 횟수가 큰 장르이름 순으로 정렬한다.

2. 위에서 구한 순서대로 dictionary에서 장르이름을 찾아 재생된 횟수가 높은 순으로 value를 정렬한다.

 

장르 음악이 한번이면 한번만 출력한다.

 

구현

dictionary는 정렬되어 있지 않은데 배열을 따로 만들어서 정렬을 해서 다시 딕셔너리를 구현해야하나?

라는 고민을 하면서 애플 공식문서를 보다가 sorted(by:) 함수가 있는 것을 발견했다.

func sorted(by areInIncreasingOrder:
	((key: Key, value: Value), (key: Key, value: Value)) throws -> Bool)
	rethrows -> [(key: Key, value: Value)]

 

정렬된 (key, value) 배열을 반환해주는 것을 알 수 있다.

 

하지만 여기선 쓰지는 않았고ㅎ..ㅎ

 

키값으로 따로 배열만들기 

+

value 따로 정렬하기

로 풀었다.

 

sorted() 함수를 쓴다면 by 클로저 안에 한거번에 작성할 수도 있을 것 같다.

 

 

전체코드

import Foundation

func solution(_ genres:[String], _ plays:[Int]) -> [Int] {
    
    var dict: Dictionary<String, [(Int, Int)]> = [:]
    var result: [Int] = []
    
    for i in 0..<genres.count {
        if let _ = dict[genres[i]] {
            dict[genres[i]]?.append((i, plays[i]))
        } else {
            dict[genres[i]] = [(i, plays[i])]
        }
    }
    
    let genresOrder = dict.keys.sorted(by: {
        dict[$0]!.reduce(0, { $0 + $1.1 }) > dict[$1]!.reduce(0, {$0 + $1.1})
    })
    
    for key in dict.keys {
        dict[key]?.sort(by: { $0.1 == $1.1 ? $0.0 < $1.0 : $0.1 > $1.1 })
    }
    
    for genre in genresOrder {
        let count = dict[genre]!.count == 1 ? 1 : 2
        for i in 0..<count {
            if let songs = dict[genre] {
                result.append(songs[i].0)
            }
        }
    }
    
    return result
}

 

https://developer.apple.com/documentation/swift/dictionary

 

Apple Developer Documentation

 

developer.apple.com