2016-12-15 4 views
0

Я пытаюсь преобразовать ниже Swift 2 метода расширения для Swift 3.«Генератор» не является типом членом «Self.SubSequence»

extension CollectionType { 

    func chunk(withDistance distance: Index.Distance) -> [[SubSequence.Generator.Element]] { 
     var index = startIndex 
     let generator: AnyGenerator<Array<SubSequence.Generator.Element>> = anyGenerator { 
      defer { index = index.advancedBy(distance, limit: self.endIndex) } 
      return index != self.endIndex ? Array(self[index ..< index.advancedBy(distance, limit: self.endIndex)]) : nil 
     } 
     return Array(generator) 
    } 

} 

инструмент преобразования Xcode оставил меня с этим.

extension Collection { 

    func chunk(withDistance distance: Int) -> [[SubSequence.Iterator.Element]] { 
     var index = startIndex 
     let generator: AnyGenerator<Array<SubSequence.Generator.Element>> = anyGenerator { 
      defer { index = index.advancedBy(distance, limit: self.endIndex) } 
      return index != self.endIndex ? Array(self[index ..< index.advancedBy(distance, limit: self.endIndex)]) : nil 
     } 
     return Array(generator) 
    } 

} 

Теперь я получаю вышеуказанную ошибку в строке, let generator: AnyGenerator<Array<SubSequence.Generator.Element>> = anyGenerator {. Я не могу понять, как это исправить.

ответ

1

Есть несколько проблем:

  • Generator был переименован в Iterator в Swift 3, и, следовательно, AnyGenerator к AnyIterator.
  • IndexDistance - ассоциированный тип Collection, который представляет собой количество шагов между индексами.
  • В Swift 3, «Коллекции перемещают свой индекс», см. A New Model for Collections and Indices о быстрой эволюции.

Собираем все вместе, ваш метод может выглядеть в Swift 3, как это:

extension Collection { 

    func chunk(withDistance distance: IndexDistance) -> [[SubSequence.Iterator.Element]] { 
     var pos = startIndex 
     let iterator: AnyIterator<Array<SubSequence.Iterator.Element>> = AnyIterator { 
      // Already at the end? 
      if pos == self.endIndex { return nil } 

      // Compute `pos + distance`, but not beyond `self.endIndex`: 
      let endPos = self.index(pos, offsetBy: distance, limitedBy: self.endIndex) ?? self.endIndex 

      // Return chunk and advance `pos`: 
      defer { pos = endPos } 
      return Array(self[pos..<endPos]) 
     } 
     return Array(iterator) 
    } 
} 

let a = [1, 2, 3, 4, 5, 6, 7] 
let c = a.chunk(withDistance: 2) 
print(c) // [[1, 2], [3, 4], [5, 6], [7]] 

Я переименовал местную index переменную pos, чтобы избежать путаницы с

public func index(_ i: Self.Index, offsetBy n: Self.IndexDistance, limitedBy limit: Self.Index) -> Self.Index? 

метод Collection, который используется для продвижения индекса.

Конечно, вы могли бы достичь того же результата с while цикла вместо Iterator:

extension Collection { 

    func chunk(withDistance distance: IndexDistance) -> [[SubSequence.Iterator.Element]] { 
     var result: [[SubSequence.Iterator.Element]] = [] 
     var pos = startIndex 
     while pos != endIndex { 
      let endPos = self.index(pos, offsetBy: distance, limitedBy: self.endIndex) ?? self.endIndex 
      result.append(Array(self[pos..<endPos])) 
      pos = endPos 
     } 
     return result 
    } 
} 
+0

Спасибо. Ваш второй подход намного чище и понятнее. – Isuru