2016-07-16 2 views
3

루프 모드에서 컬렉션을 무한히 반복하는 iterator를 찾고 있습니다. 따라서 컬렉션의 끝 인덱스에 도달하면 반복기는 시작 인덱스에서 요소를 반환해야합니다.루프 모드에서 컬렉션을 무한 반복하는 사용자 정의 반복자

다음 해결책은 효과가있는 것 같지만 더 나은 방법으로 만들 수 있기를 바랍니다.

public struct LoopIterator<T: Collection>: IteratorProtocol { 

    private let collection: T 
    private var startIndexOffset: T.IndexDistance 

    public init(collection: T) { 
     self.collection = collection 
     startIndexOffset = 0 
    } 

    public mutating func next() -> T.Iterator.Element? { 
     guard !collection.isEmpty else { 
     return nil 
     } 
     let index = collection.index(collection.startIndex, offsetBy: startIndexOffset) 
     startIndexOffset += T.IndexDistance(1) 
     if startIndexOffset >= collection.count { 
     startIndexOffset = 0 
     } 
     return collection[index] 
    } 
} 

extension Array { 
    func makeLoopIterator() -> LoopIterator<Array> { 
     return LoopIterator(collection: self) 
    } 
} 

// Testing... 
// Will print: 1, 2, 3, 1, 2, 3 
var it = [1, 2, 3].makeLoopIterator() 
for _ in 0..<6 { 
    print(it.next()) 
} 

맞춤 반복기는 올바른 방법입니까? 무엇을 개선 할 수 있습니까?

감사합니다.

+1

나중에 참조 할 수 있도록 작업 코드 개선에 대한 질문은 ** Code Review ** 스택 교환에 더 적합 할 것입니다. http://codereview.stackexchange.com/ –

+1

IMO, codereview.se는 일반적인 관심이 거의없고 명시 적으로 검색되지 않을 코드 검토에 가장 적합합니다. 즉, 모범 사례는 코드가 아닌 관심 대상입니다.). 이 질문은 전반적으로 흥미로운 코드에 대해 다루고 있으며 광범위한 관심 주제 (Swift 3 인덱스의 올바른 사용)에 특히 중점을두고 있으며 향후 검색 될 가능성이 높습니다. 포스터에 코드가 포함되어 있지 않았다면 그들은 "당신은 무엇을 시도 했습니까?" 코멘트. 코드에 코드가 포함되어 있으면 codereview로 리디렉션하는 것이 불공정 해 보입니다. –

답변

6

Swift 3 (사용중인)에서 색인은 컬렉션 자체에서 고급으로 작성됩니다.

public struct LoopIterator<Base: Collection>: IteratorProtocol { 

    private let collection: Base 
    private var index: Base.Index 

    public init(collection: Base) { 
     self.collection = collection 
     self.index = collection.startIndex 
    } 

    public mutating func next() -> Base.Iterator.Element? { 
     guard !collection.isEmpty else { 
      return nil 
     } 

     let result = collection[index] 
     collection.formIndex(after: &index) // (*) See discussion below 
     if index == collection.endIndex { 
      index = collection.startIndex 
     } 
     return result 
    } 
} 

이제 우리는 단순히 앞으로 인덱스를 이동하고 지금 말을 가리키는 경우, 처음으로 재설정 다음과 같이두고, 당신은이를 단순화 할 수 있습니다. count 또는 IndexDistance은 필요 없습니다.

여기서 Iterator는 모든 콜렉션 (및 모든 색인)에서 작동하므로 다소 애매한 경우 (특히 AnyIndex)의 성능을 향상시키기 위해 여기에 formIndex을 사용했습니다. 더 간단한 버전은 index = collection.index(after: index)이고 대부분의 경우 더 좋을 수 있습니다.

스위프트 3 지수에 대한 자세한 내용은 SE-0065을 참조하십시오.