[Swift] contains(_:) 메서드

개요

어떤 언어던지 코딩을 하다 보면, Array나 set등의 collection에서 내가 원하는 element를 찾고자 하는 경우들이 더러 있습니다. 코테라던가…코딩테스트라던가..😅

이때 Swift로 코딩 한다면, 자주 사용하게 되는 contains(_:)메서드를 알아보려고 합니다.

contains(_:) 메서드는 스위프트 곳곳에 다양하게 오버로딩되어 있는 메서드인데, 다양한 형태의 메서드를 다뤄보고, 각 특징들을 살펴보도록 합니다.🙌



1. Array > contains(_:)

먼저 Array에서의 contains를 공식문서에서 보면,

두 가지 메서드가 있는 것을 볼 수 있습니다.


먼저 contains(Element) -> Bool을 확인해 보면,

위와 같이 사용하게 되면, Array sequence에 찾고자 하는 element가 있는지 확인하고 Boolean 값을 리턴해 준다고 하네요.

배열의 요소들에 각각 접근하고 비교하는 것 보다 훨씬 간단하게 코드를 작성할 수 있을 것으로 기대됩니다.

그럼 직접 사용해 보도록 하겠습니다

1
2
3
4
5
6
7
8
let arrayInt: [Int] = [1, 2, 3, 4, 5]
let target: Int = 3
if arrayInt.contains(target) {
print("\(target)있음!")
} else {
print("\(target)없음!")
}
// 3있음!

Int 형 뿐만 아니라 다른 타입들도 가능합니다

1
2
3
4
5
6
7
8
9
let arrayDouble: [Double] = [1.0, 2.0, 3.0, 4.0]
let target: Double = 3.0

if !arrayDouble.contains(target) {
print("\(target)있음!")
} else {
print("\(target)없음!")
}
// 3.0있음!

여기서 다른 타입이라고 하면, 문서에 쓰인 선언부를 다시 확인해 볼 필요가 있습니다.

Equatable 프로토콜로 구성될 수 있는 타입이면, 오케이라는 건데, 간단히 말하면 서로 비교할 수 있으면 된다는 의미입니다.

Equatable에 대한 자세한 내용은 추후 다뤄보고자 하지만(맨날 말만..), iOS블로그에서 유명하신 Zedd님의 블로그 글을 참고하시면 좋을 것 같습니다!

Swift ) Equatable - ZeddiOS

서로 비교가 가능하려면 타입이 같아야 할텐데, 다른 타입이라면 타입캐스팅등의 방법을 통해 사용할 수 있을 것 같습니다.

이런 점 때문에 아래와 같은 Any 타입의 Array는 컴파일 에러를 뿜게 됩니다.


그럼 이어서 두 번째 메서드인
contains(where: (Element) -> Bool) -> Bool를 보도록 하겠습니다.

주어진 predicate를 Element가 만족하는지 판별해서 Boolean 타입의 값을 리턴해준다는 건데,

클로져를 이용해서 조건을 형성해 줄 수 있음을 의미합니다.


예를 들어보면,

1
2
3
4
5
6
7
8
9
10
11
let arrayInt: [Int] = [1, 2, 3, 4, 5]
let hadEvenNum = arrayInt.contains { element -> Bool in
if element % 2 == 0 {
print("true")
return true
} else {
print("false")
return false
}
}
print(hadEvenNum) // 'hadEvenNum' == true

위와 같이, sequence에서 loop문을 통해 각 요소에 접근해 후행클로져에 주어진 조건이 만족하는 경우에 메서드가 결과 값을 반환하고 종료됩니다!

이를 보면, 눈치 빠르신 분들은 contains 메서드는 O(n)의 복잡도를 갖음을 알 수 있으실 겁니다 ㅎㅎ


추가로 클로져를 사용하니 당연히 인자 값을 축약해서 사용할 수도 있습니다.

1
2
3
let numbers = [1, 2, 3, 4, 5]
let hadOddNum = numbers.contains { $0 % 2 == 1 }
// 'hadOddNum' == true


2. Set > contains(_:)

공식문서의 예제인데, 외관상 동일해 보입니다?
그런데 상단예제 이미지의 최하단을 보시면, 복잡도가 O(1)이네요!

왜 일까요?

바로 SetHashable 프로토콜을 따르기 때문입니다.

Hash는 hash function을 통해 key & value쌍을 이루어 데이터를 저장하는 자료구조인데요.

hash를 구현 할 때, Hash Collision(해시 충돌)을 방지하기 위한 Chaining이 일어나고, 최악의 경우 Hash의 Linked List를 차례로 살펴보아야 한다면, O(n)의 복잡도를 가지게 되겠지만, 평균적으로 삽입, 삭제, 검색을 하는데 O(1)의 복잡도를 가지게 되죠.


따라서, Swift에서 제공하는 Set 또한 Hashable 프로토콜을 사용하기 때문에, Search의 기능을 수행하는 contains(_:)를 사용하면 평균적으로 O(1)의 복잡도를 가진다고 기재해 놨네요 😇

다양한 API를 제공해 주는 것이 어떤 부분에선 iOS개발의 장점인 것 같아요



3. String > contains(_:)

마지막으로 다뤄볼 contains(_:) 메서드는 String 문자열을 검색할 때 사용하는 메서드입니다

1
2
3
4
5
var string = "Swift is awesome!"
let target = "some"
if string.contains(target) {
print("\(target) 있음!")
}

심플하죠. 찾고자 하는 문자열을 인자로 넣어주면, String을 검사해서 일치하는 문자열이 있는지 Boolean타입으로 리턴해줍니다.

xcode를 이용해 자동완성을 시켜보려하면 문자열과 관련해서 아래와 같이 세개의 contains(_:) 메서드를 제공해 주는데

최상단의 contains(where: )는 클로져를 통해 조건을 추가할 수 있는 것이고, 하단의 두 메서드는 Character 문자나 String 문자열을 검색하여 Boolean 타입을 리턴해 주는 메서드로 위에서 소개했던 메서드들과 같습니다!



오늘은 Swift에서 제공하는 contains(_:) 메서드들을 한 번 훑어보았는데, 다양한 타입과 프로토콜 별로 그에 상응하는 메서드를 제공해 줌을 볼 수 있었습니다.

좀 더 deep하게 들어가면, enum 이나 class로 이루어진 Array에서도 contains(_:) 메서드를 사용할 수 있는데, 아래의 애플 공식문서 예제를 봐도 좋을 것 같습니다 😄

피드백이나 지적은 항상 환영입니다. 😇



참고 :