Notice
Recent Posts
Recent Comments
Link
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Archives
Today
Total
관리 메뉴

cchanmi

[Swift] Dictionary, Set 들어온 순서대로 값 출력하기 본문

Swift

[Swift] Dictionary, Set 들어온 순서대로 값 출력하기

cchanmi 2023. 5. 13. 00:06

Dictionary와 Set은 내부적으로 hashTable로 구성되어 있기 때문에, 순서가 보장되지 않죠.

가끔 Dictionary와 Set으로 값을 찾으면 딱 좋은 상황인데, 값이 들어온 순서대로 출력해야 하는 상황을 겪는다면 어떻게 해야 할까요?

 

그럴 때마다 항상 Dictionary와 Set을 포기했었는데, 이번에 원하는대로 출력할 수 있는 로직을 구현해 보게 되어서 기록해 두려고 합니다. ㅎㅎ

 


해당 함수는 입출력으로 [1, 2, 3, 3, 3, 3, 4, 4]라는 배열을 주고 있습니다.

여기서 중복되는 배열의 값일 경우, 그 중복값을 count 하여 출력해 주고자 합니다.

단, 먼저 나온 순서대로 출력하고자 합니다.

 

예를 들면 위의 입출력에서는 

Dicrionary를 이용한 로직

func solution_version_Dictionary(_ array: [Int]) -> [Int] {
    var dic = [Int:(order: Int, count: Int)]()
    
    func sameValueCount(_ array: [Int]) {
        var order = 1
        for i in 0..<array.count {
            let number = array[i]
            
            if let temp = dic[number] {
                dic[number] = (order: temp.0, count: temp.1+1)
                continue
            }
            
            dic[number, default: (0, 0)] = (order: order, count: 1)
            order += 1
        }
    }
    
    sameValueCount(array)
    
    var resultArray = dic.filter { $0.value.1 > 1 }.sorted(by: { $0.value.order < $1.value.order}).map{ $0.value.count }
    
    return resultArray.isEmpty ? [-1] : resultArray
}

print(solution_version_Dictionary([1, 2, 3, 3, 3, 3, 4, 4])) // [4, 2]
print(solution_version_Dictionary([3, 2, 4, 4, 2, 5, 2, 5, 5])) // [3, 2, 3]
print(solution_version_Dictionary([3, 5, 7, 9, 1])) // [-1]

Int 타입의 key를 가지고, value로 튜플 타입(order, count)의 Int 값들을 담을 수 있는 dictionary를 만들어 두었구요.
순서 변수인 order를 하나 만들어 줍니다.

dictionary에 해당 key에 접근하였을 때, value가 있다면, value.order는 증가할 필요가 없고, 중복 횟수는 +1을 해 줍니다.

그리고 다음 순서로 값을 저장해 주기 위해 order += 1을 해 주고요

 

반대로 dictionary를 통해 해당 key에 접근하였지만, value가 없어서 nil 값이 나오는 경우는 value.order에 해당 순서인 order 값을 넣어 주고, count는 1을 넣어 줍니다.

 

마지막으로 중복값이기 때문에 1보다 큰 경우만 사용하기 위해 filter 함수를 사용해 주고,

!!!value.order를 기준으로!! 오름차순으로 정렬해 주고, value.count를 배열로 묶어 주면 원하는 값을 도출할 수 있습니다!!

 

Set을 이용한 로직

func solution_Version_Set(_ array: [Int]) -> [Int] {
    var set: Set<Int> = []
    var orderAndCountArray = Array(repeating: (order: 0, count: 0), count: 101)
    
    func sameValueCount(_ array: [Int]) {
        var order = 1
        for i in 0..<array.count {
            let number = array[i]
            
            if let temp = set.update(with: number) {
                let (tempOrder, tempCount) = orderAndCountArray[temp]
                orderAndCountArray[temp] = (order: tempOrder, count: tempCount+1)
                continue
            }
            orderAndCountArray[number] = (order: order, count: 1)
            order += 1
        }
    }
    
    sameValueCount(array)
    
    let resultArray = orderAndCountArray.filter { $0.count > 1 }.sorted(by: { $0.order < $1.order }).map{ $0.count }

    return resultArray.isEmpty ? [-1] : resultArray
}

print(solution_Version_Set([1, 2, 3, 3, 3, 3, 4, 4])) // [4, 2]
print(solution_Version_Set([3, 2, 4, 4, 2, 5, 2, 5, 5])) // [3, 2, 3]
print(solution_Version_Set([3, 5, 7, 9, 1])) // [-1]

Set을 이용해서도 비슷한 로직으로 구현할 수 있습니다.

개인적으로 저는 dictionary 구현 방식이 더 좋은 것 같네요!

Comments