Bibi's DevLog πŸ€“πŸŽ

[Array] contains(_:) + μ‹œκ°„λ³΅μž‘λ„ 탐ꡬ λ³Έλ¬Έ

πŸ“±πŸŽ iOS/🍏 Apple Developer Documentation

[Array] contains(_:) + μ‹œκ°„λ³΅μž‘λ„ 탐ꡬ

λΉ„λΉ„ bibi 2023. 1. 26. 00:04

[Array] contains(_:) + μ‹œκ°„λ³΅μž‘λ„ 탐ꡬ

Apple Developer Documentation

μ‹œν€€μŠ€κ°€ 주어진 μš”μ†Œλ₯Ό ν¬ν•¨ν•˜κ³ μžˆλŠ”μ§€λ₯Ό λ‚˜νƒ€λ‚΄λŠ” λΆˆλ¦¬μ–Έ 값을 λ°˜ν™˜ν•©λ‹ˆλ‹€.

μ„ μ–Έ

func contains(_ element: Self.Element) -> Bool

Element κ°€ Equatable 을 μ€€μˆ˜ν•  λ•Œ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

리턴값

λ§Œμ•½ μ‹œν€€μŠ€ λ‚΄μ—μ„œ 주어진 μš”μ†Œκ°€ 발견되면 true, 그렇지 μ•ŠμœΌλ©΄ false.

νŒŒλΌλ―Έν„°

element : μ‹œν€€μŠ€μ—μ„œ 찾고자 ν•˜λŠ” μš”μ†Œ.

μ„€λͺ…

이 μ˜ˆμ‹œλŠ” μ˜ν™”μ˜ 캐슀트λ₯Ό λ‹΄κ³  μžˆλŠ” 배열에 κ°€μž₯ μ’‹μ•„ν•˜λŠ” λ°°μš°κ°€ μžˆλŠ”μ§€ 보기 μœ„ν•΄ ν™•μΈν•©λ‹ˆλ‹€.

let cast = ["Vivien", "Marlon", "Kim", "Karl"]
print(cast.contains("Marlon"))
// Prints "true"
print(cast.contains("James"))
// Prints "false"

λ³΅μž‘λ„

O(n), n은 μ‹œν€€μŠ€μ˜ 길이.


(μ•„λž˜λŠ” μ œκ°€ μž‘μ„±ν•œ λ‚΄μš©μž…λ‹ˆλ‹€)

contains(_:) 의 μ‹œκ°„λ³΅μž‘λ„ 탐ꡬ

Arrayμ—μ„œ μ‹œκ°„λ³΅μž‘λ„λŠ” O(n) 이라고 κ³΅μ‹λ¬Έμ„œμ—μ„œ λ§ν•œλ‹€.

ν•˜μ§€λ§Œ νƒμƒ‰ν•˜λŠ” μš”μ†Œλ₯Ό 빨리 찾으면 빨리 뢈린 값이 λ°˜ν™˜λ˜μ§€ μ•Šμ„κΉŒ?

νƒμƒ‰ν•˜λŠ” μš”μ†Œκ°€ λ°°μ—΄μ˜ μ•ž/쀑앙/뒀에 μžˆμ„ λ•Œ 각각 κ±Έλ¦¬λŠ” μ‹œκ°„μ„ μ•Œμ•„λ³΄μ•˜λ‹€.

let startTime = CFAbsoluteTimeGetCurrent()
var arr = Array(repeating: 0, count: 1_000_000)
var arrFirst1 = arr
arrFirst1.insert(1, at: 0)
var arrMiddle1 = arr
arrMiddle1.insert(1, at: arrMiddle1.count / 2)
var arrLast1 = arr
arrLast1.append(1)
print(arrFirst1.contains(1))
//        print(arrMiddle1.contains(1))
//        print(arrLast1.contains(1))
let endTime = CFAbsoluteTimeGetCurrent()
print(endTime - startTime) // 0.00533902645111084

μœ„μ™€ 같은 예제 μ½”λ“œλ₯Ό λ§Œλ“€μ–΄ μ‹€ν–‰μ‹œκ°„μ„ μΈ‘μ •ν•΄ λ³΄μ•˜λ‹€.

0으둜 μ±„μ›Œμ§€κ³  길이가 1,000,000인 배열에 맨 μ•ž(arrFirst1), 쀑간(arrMiddle1), 맨 λ’€(arrLast1) 에 1을 λ„£λŠ”λ‹€.

그리고 각각의 배열에 contains(1) 을 μ μš©ν•˜λ©΄ μ–Όλ§ˆλ‚˜ κ±Έλ¦¬λŠ”μ§€ μΈ‘μ •ν•œλ‹€.

(μ •ν™•ν•œ μ‹œκ°„ 츑정을 μœ„ν•΄ contains 쀄은 ν•˜λ‚˜λ§Œ 남기고 λ‚˜λ¨Έμ§€λŠ” μ£Όμ„μ²˜λ¦¬ν•΄ μ‹€ν–‰ν•˜λŠ” μ‹μœΌλ‘œ 진행)

print(arrFirst1.contains(1)) // 0.00533902645111084
print(arrMiddle1.contains(1)) // 0.03761601448059082
print(arrLast1.contains(1)) // 0.06794404983520508

ν™•μ‹€νžˆ μ°ΎλŠ” μš”μ†Œκ°€ 맨 μ•žμ— μžˆμ„ λ•Œ κ°€μž₯ 빨랐고, μ°ΎλŠ” μš”μ†Œκ°€ 맨 뒀에 있으면 κ°€μž₯ λŠλ Έλ‹€.

그리고 μ°ΎλŠ” μš”μ†Œκ°€ 쀑간에 있으면 μ‹œκ°„λ„ 쀑간 μ •λ„λ‘œ κ±Έλ Έλ‹€.

λ°°μ—΄μ˜ 길이가 κΈΈμ–΄μ§ˆμˆ˜λ‘ μ‹€ν–‰μ‹œκ°„μ˜ 차이가 ν™•μ‹€νžˆ λ“œλŸ¬λ‚¬λ‹€.

μ•„λž˜λŠ” λ°°μ—΄μ˜ 길이가 1,000,000,000일 λ•Œ (var arr = Array(repeating: 0, count: 1_000_000_000)의 μ‹€ν–‰μ‹œκ°„μ΄λ‹€.

print(arrFirst1.contains(1)) // 14.913639068603516
print(arrMiddle1.contains(1)) // 46.19543790817261
print(arrLast1.contains(1)) // 78.79820799827576

λ§ˆμ§€λ§‰μœΌλ‘œ μ°ΎλŠ” μš”μ†Œκ°€ 없을 λ•Œμ˜ μ‹€ν–‰μ‹œκ°„μ€ μ–΄λ–¨κΉŒ?

길이가 1,000,000이고 0으둜만 μ±„μ›Œμ§„ μ›λž˜μ˜ λ°°μ—΄ (arr) 에 contains(1) 을 μ μš©ν•΄ μ–Όλ§ˆλ‚˜ κ±Έλ¦¬λŠ”μ§€ μΈ‘μ •ν•΄ λ³΄μ•˜λ‹€.

let startTime = CFAbsoluteTimeGetCurrent()
var arr = Array(repeating: 0, count: 1_000_000)
var arrFirst1 = arr
arrFirst1.insert(1, at: 0)
var arrMiddle1 = arr
arrMiddle1.insert(1, at: arrMiddle1.count / 2)
var arrLast1 = arr
arrLast1.append(1)
print(arr.contains(1))
let endTime = CFAbsoluteTimeGetCurrent()
print(endTime - startTime) // 0.06914293766021729

κ²°κ³ΌλŠ” μœ„μ™€ κ°™μ•˜λ‹€. (λ¬Όλ‘  μ‹€ν–‰ μ‹œλ§ˆλ‹€ μ˜€μ°¨λŠ” μ‘°κΈˆμ”© μžˆλ‹€)

print(arrFirst1.contains(1)) // 0.00533902645111084
print(arrMiddle1.contains(1)) // 0.03761601448059082
print(arrLast1.contains(1)) // 0.06794404983520508
print(arr.contains(1)) // 0.06914293766021729

1이 μ—†λŠ” λ°°μ—΄μ—μ„œ 1이 μžˆλŠ”μ§€ μ—†λŠ”μ§€ ν™•μΈν•˜λ €λ©΄, κ²°κ΅­ λ°°μ—΄μ˜ 전체 μš”μ†Œλ₯Ό λκΉŒμ§€ 탐색해야 ν•œλ‹€.

κ·Έλž˜μ„œ λ°°μ—΄μ˜ λ§ˆμ§€λ§‰μ— 1이 μžˆλŠ” 경우(arrLast1) 보닀 μ•½κ°„μ˜ μ‹œκ°„μ΄ 더 κ±Έλ¦° 것을 확인할 수 μžˆμ—ˆλ‹€.

결둠적으둜 Array.contains(_:) 의 μ‹œκ°„λ³΅μž‘λ„κ°€ O(n)인 것은 λ§žμ§€λ§Œ (μ‹œκ°„λ³΅μž‘λ„λŠ” μ΅œμ•…μ˜ 경우λ₯Ό κ°€μ •ν•˜λ―€λ‘œ), 이 λ©”μ„œλ“œλŠ” λ°°μ—΄μ˜ 첫 μš”μ†ŒλΆ€ν„° ν•˜λ‚˜μ”© νƒμƒ‰ν•˜λ―€λ‘œ, μ°ΎλŠ” μš”μ†Œκ°€ μ•žμ— μžˆλ‹€λ©΄ 이보닀 μ‹€ν–‰μ‹œκ°„μ΄ μ§§μ•„μ§ˆ 수 μžˆλ‹€λŠ” 사싀을 μ•Œκ²Œ λ˜μ—ˆλ‹€!