티스토리 뷰

Swift

[스위프트] Collection 프로토콜

Hani_Levenshtein 2021. 8. 28. 17:50

안녕하세요 Hani입니다.

이번에는 Collection 프로토콜에 대하여 알아볼 거예요. 🥰

 

 

 

먼저, Collection을 알기 위해 먼저 조사해야 할 것들이 있습니다.

IteratorProtocol 프로토콜부터 보시져 🧐

 

public protocol IteratorProtocol  {
  associatedtype Element

  public mutating func next() -> Self.Element? 
}

IteratorProtocol 프로토콜을 채택한 타입은 구현한 next메서드를 통해 순차적으로 순회하는 Iterator가 됩니다.

뭐를 순회 하냐면..

 

public protocol Sequence {
  associatedtype Element where Self.Element == Self.Iterator.Element

  associatedtype Iterator: IteratorProtocol

  public func makeIterator() -> Self.Iterator 
}

Sequence를 순회하게 됩니다.

Sequence는 아까 정의한 Iterator를 반환하는 메서드를 가지고 있는데

Sequence 프로토콜을 채택한 타입은 메서드로 얻은 Iterator를 통해 element를 순차적으로 순회할 수 있습니다.

 

 

for element in sequence {
    if ... some condition { break }
}

for element in sequence {
    // No defined behavior
}
In this case, you cannot assume either that a sequence will be consumable and will resume iteration, or that a sequence is a collection and will restart iteration from the first element. A conforming sequence that is not a collection is allowed to produce an arbitrary sequence of elements in the second for-in loop.

단, Sequence를 순회하다가 중간에 마쳤을 때, 다음 순회 시 이어서 작동할지 처음부터 작동할 지 알 수 없습니다.

 

 

next를 통해 지나간 element를 더 이상 iterate할 수 없는 iteration을 destructive iteration이라고 하는데 

다음 Iteration에서도 처음부터 시작(nondestructive)하기 위해선 Collection 프로토콜을 순응할 필요가 있습니다.

 

 

Collection은 element를

1. nondestructively하게 여러 번 순회할 수 있고

2. 서브스크립트를 통해 random access가 가능한

Sequence라고 할 수 있어요.

 

Collection 프로토콜은 nondestructive iteration를 보증하기 때문에 널리 채택되고 있습니다.

public protocol Collection : Sequence { 

}

let word = "Swift"

//traverse using iterator
for character in word {
    if character == "i" { break }
    print(character)
}
// Prints "S"
// Prints "w"

//traverse using subscript
for i in word.indices {
    print(word[i])
}
// Prints "S"
// Prints "w"
// Prints "i"
// Prints "f"
// Prints "t"

 

 

 

Collection 프로토콜을 채택하는 더 깊은 프로토콜 또한 존재합니다.

public protocol BidirectionalCollection : Collection {

}

let word = "Swift"
for character in word.reversed() {
    print(character)
}
// Prints "t"
// Prints "f"
// Prints "i"
// Prints "w"
// Prints "S"

BidirectionalCollection 프로토콜은 Collection과 거의 동일하나 역방향으로 탐색할 수 있는 장점이 있습니다.

 

 

하지만 BidirectionalCollection는 element의 개수를 알려주는 count 프로퍼티의 연산 시간이 O(n)이 걸리는 문제가 있어요. 🥺

(상위 프로토콜도 역시 O(n))

 

 

이를 해결하기 위한 프로토콜도 준비되어 있습니다.

public protocol RandomAccessCollection : BidirectionalCollection {

}

RandomAccessCollection은 인덱스를 어느 거리든 O(1)에 이동할 수 있기 때문에 count 프로퍼티의 연산 시간도 O(1)입니다.

 

 

 

Sequence를 순응하거나 Collection을 순응하는 더 많은 프로토콜이 있는데

이번 포스팅에서는 여기까지만 다루도록 하겠습니다. ☺️


References

https://developer.apple.com/documentation/swift/iteratorprotocol

https://developer.apple.com/documentation/swift/sequence

https://developer.apple.com/documentation/swift/collection/

 

 

 

 

 

 

댓글