allSatisfy()

작업을 하다보면, 특정 값들이 모두 true 조건인지 확인해야 할 때가 있습니다.

예를들면 아래와 같은 것들이 있겠네요.

1. 회원가입 화면의 login, password, password repeat 값이 모두 유효한지 2. 개인정보동의 값에서 필수/선택 값들을 유효하게 선택했는지

Swift 에서는 이런 경우에 사용할 수 있는 allSatisfy 메소드를 지원합니다. SE-0207 에서 제안되었고, Swift 4.2 버전부터 지원하고 있어요. 생각보다 간단하고 저희가 기존과 썼던 방법과 크게 다르지 않으니 바로 살펴보겠습니다.

allSatisfy(_:) Returns a Boolean value indicating whether every element of a sequence satisfies a given predicate.

func allSatisfy(_ predicate: (Self.Element) throws -> Bool) rethrows -> Bool

iOS 8.0+ iPadOS 8.0+ macOS 10.10+ Mac Catalyst 13.0+ tvOS 9.0+ watchOS 2.0+

문서에서는 위와 같이 설명하고 있는데요. 시퀀스의 모든 요소가 주어진 조건을 만족하는지의 여부에 따라 Bool 타입을 리턴해주고 있어요. 모두 만족하면 true, 그렇지 않다면 false 를 말하는 거겠죠? 코드를 볼게요.

지금 names 라는 시퀀스가 있고, 해당 시퀀스 내부의 값들의 길이가 모두 5 이상인 경우를 체크한다고 해보죠.

let names = ["Sofia", "Camilla", "Martina", "Mateo", "Nicolás"]

for loop

먼저 for문을 사용하는 경우입니다. 익숙하지만, 고차함수를 사용하면 왠지 더 축약할 수 있을 것 같아요.

//for loop
func allHaveAtLeastFive(_ names: [String]) -> Bool {
    for name in names {
        if name.count < 5 {
            return false
        }
    }
    return true
}

filter

고차함수인 filter를 사용하면 어떨까요 ? 2가지 방법을 적어봤는데, 둘 다 for문 보다는 훨씬 간결하죠. 체이닝하면서 바로 작업할 수 있구요.

let allHaveAtLeastFiveFilter1 = names.filter({ $0.count >= 5 }).count == names.count
let allHaveAtLeastFiveFilter2 = names.filter({ $0.count < 5 }).isEmpty

allSatisfy

그럼 allSatisfy 를 사용하면 어떨까요 ? filter보다도 코드의 길이가 약간 더 축약되네요.

let allHaveAtLeastFive = names.allSatisfy({ $0.count >= 5 })

이쯤되면 이런 생각을 하실 수 있어요. "아니 그럼 더 익숙한 filter를 쓰지 굳이 왜 allSatisfy를 써?" 라고 말이죠. 그런데, filter와 allSatisfy를 잘 보시면 묘하게 다르다는 것을 볼 수 있어요.

filter는 해당 조건을 만족하는 시퀀스를 리턴하죠. 그래서 allHaveAtLeastFiveFilter1 의 방법으로는 필터를 한 번 걸고 해당 시퀀스의 count 값이 주어진 name의 count 값과 같은지를 비교하는 연산이 추가됩니다. 또 다른 allHaveAtLeastFiveFilter2 의 방법은 isEmpty라는 속성으로 더 간단하지만, 주어진 제한 조건을 반대로 $0.count < 5 처럼 한번 꺾어주어야 된다는 단점이 있어요. 그만큼 가독성이 떨어진다는 얘기죠.

하지만, allSatisfy는 위에서 보신 것처럼 주어진 제한 조건을 그대로 읽을 수 있고, 코드도 더 간결하죠. 그래서 문서에 나와있는 것처럼 어떤 특정 시퀀스의 조건을 모두 만족하는 지를 판단할 때는 꽤나 유용하게 사용할 수 있어요.

Conclusion

  • Swift에서는 시퀀스의 모든 요소가 주어진 조건을 만족하는지의 여부를 판단하는 메소드로 allSatisfy를 지원합니다.

  • 기존의 for loop, filter, contain 등을 사용해도 되지만, allSatisfy연산, 가독성, 축약 부분에서 더 뛰어납니다.

Reference

https://developer.apple.com/documentation/swift/array/allsatisfy(_:)

https://github.com/apple/swift-evolution/blob/master/proposals/0207-containsOnly.md

Last updated