티스토리 뷰

Swift

Swift ) 정렬 (2) - Sort by two criteria

Zedd0202 2020. 11. 24. 13:42
반응형

안녕하세요 :) Zedd입니다.

정렬 (1)글을 썼는데요, 이번엔 조금 복잡한 정렬을 해보겠습니다. 

struct PullRequest {
    
    var title: String
    var createdDate: Date?
    var approved: Bool
}

let pullRequests = [
    PullRequest(title: "알렌 워커", createdDate: Calendar.current.date(byAdding: .hour, value: -1, to: Date()), approved: true),
    PullRequest(title: "카이고", createdDate: Calendar.current.date(byAdding: .hour, value: -2, to: Date()), approved: false),
    PullRequest(title: "마시멜로우", createdDate: Calendar.current.date(byAdding: .hour, value: -3, to: Date()), approved: false),
    PullRequest(title: "제드", createdDate: Calendar.current.date(byAdding: .hour, value: -4, to: Date()), approved: true),
    PullRequest(title: "마데온", createdDate: Calendar.current.date(byAdding: .hour, value: -5, to: Date()), approved: false),
    PullRequest(title: "마틴개릭스", createdDate: Calendar.current.date(byAdding: .hour, value: -5, to: Date()), approved: true)
]

대충 이런겁니다. 코드가 복잡해보이는데..그냥 

title -> PR 제목

createdDate -> 만들어진 날짜

approved -> approve되었는지.

 

저는 오래된 순으로 정렬하고 싶은데, approve된 건 가장 하단에 위치했으면 좋겠습니다.

이럴 때 정렬을 어떻게 해야할까요?

정렬 (1)ㅇㅔ서 언급했다시피, 

첫번째 인수가 두번째 인수보다 먼저 정렬되어야 하는 경우 areInIncreasingOrder가 true를 리턴하게 하면 됩니다. 

let sorted = pullRequests.sorted { (first, second) -> Bool in
    //
}

먼저 하고싶은건,

1. 오래된 순으로 정렬.

2. approve된것은 가장 하단에.

입니다.

 

# 과정

정렬을 하는 다양한 방법이 있는데 저는 그냥..제가 한 방법을 소개해드리려고 합니다.

일단 우리가 어떻게 정렬을 해야하는지 생각해보겠습니다. 

가장 하단 Boolean이 approve되었는지 여부입니다. 

True이면 가장 뒤로 보내면 됩니다. 

일단 approve여부를 검사하는게 쉬우니, approved 기준으로 검사하겠습니다.

let sorted = pullRequests.sorted { (first, second) -> Bool in
    if first.approved != second.approved {
        return ??
    }
    return ??
}

first와 second의 approved값이 서로 다르다면, 어떻게 하면 될까요? 

가장 중요한건 True가 "뒤로" 보내져야 한다는걸 기억하면 됩니다.

let sorted = pullRequests.sorted { (first, second) -> Bool in
    if first.approved != second.approved {
        return ??
    }
    return ??
}

first : 카이고

second : 알렌워커 

입니다.

알렌워커의 approved가 true && approve 된 건 뒤로 보내고 싶기 때문에

지금과 같은 상황에서는 순서를 바꾸어야 합니다.

즉 true를 리턴하면 됩니다.

let sorted = pullRequests.sorted { (first, second) -> Bool in
    if first.approved != second.approved {
        return true
    }
    return ??
}

이렇게 하면 될 것 같지만, 무조건 true를 리턴하면 안됩니다. 

왜냐? 

이와 같은 상황 때문이죠..

first : 제드

second : 마시멜로우 

제드가 approve되었으므로 마시멜로우보다 "뒤에 있는게" 제가 원하는겁니다.

하지만 여기서 True를 리턴해버리면, 마시멜로우와 제드의 순서가 바뀌게 되어

제드 - 마시멜로우 순이 됩니다.

 

그렇다면 패턴이 보입니다. 만약 first가 false이면 true를 리턴하면 됩니다!

그러면

알렌워커(True) - 카이고(False) -> true리턴 

마시멜로우(False) - 제드(True) -> false리턴. 

즉, 

let sorted = pullRequests.sorted { (first, second) -> Bool in
    if first.approved != second.approved {
        return !first.approved
    }
    return ??
}

이렇게 하면 됩니다.

자..그럼 if statement아래에 있는 저 return이 무엇을 리턴하든

approve된건 아래에 위치하게 됩니다.

 

1. 오래된 순으로 정렬.

2. approve된것은 가장 하단에.

 

2번조건이 만족되었으니 1번조건만 만족하면 됩니다.

오래된 순으로 정렬한다는것은 createdDate가 가장 빠른것 부터 정렬한다는 소리겠죠?

createdDate로 오름차순 정렬을 하면 됩니다.

즉, 

let sorted = pullRequests.sorted { (first, second) -> Bool in
    if first.approved != second.approved {
        return !first.approved
    }
    return first.createdDate < second.createdDate
}

이렇게 되는것이죠.

 

# 결과 

결과입니다.

오늘이 24일인데, 19일에 만들어지고 아직까지 approve안되었으니 마데온 PR을 가장 먼저봐야합니다.

그리고 approve된 건 가장 하단에 위치하게 되었습니다!

 

질문이나 틀린 점이 있다면 댓글 남겨주시면 감사하겠습니다!

반응형

'Swift' 카테고리의 다른 글

Swift ) ARC / Strong Reference Cycle 해결 방법(weak, unowned)  (4) 2021.02.18
Swift ) 정렬 (3) - Sort by multiple criteria  (1) 2020.11.24
Swift ) 정렬 (1)  (0) 2020.11.23
Swift 5.3 released!  (3) 2020.09.17
Swift ) URLComponents  (0) 2020.08.23