Chunking Collections and Strings in Swift 5.1

Quick version that follows more of a collection consumer approach. This also has an example that illustrates the issue with the Int constrained version.

extension Collection {
  public func chunked_orignal(into size: Int) -> [SubSequence] {
    var chunks: [SubSequence] = []
    var i = startIndex

    while let nextIndex = index(i, offsetBy: size, limitedBy: endIndex) {
      let chunk = self[i ..< nextIndex]
      chunks.append(chunk)
      i = nextIndex
    }

    if i != endIndex {
      chunks.append(self[i...])
    }

    return chunks
  }
}

print("Original")
print([1,2,3,4,5,6,7,8,9,10].chunked_orignal(into: 2))
print([1,2,3,4,5,6,7,8,9,10].lazy.filter { $0 % 2 == 0 }.chunked_orignal(into: 2).map { Array($0) })

extension Collection where Index == Int {
  public func chunked_broken(into size: Index.Stride) -> [SubSequence] {
    return stride(from: startIndex, to: endIndex, by: size).map { index in
      let end = self.index(index, offsetBy: size, limitedBy: self.endIndex) ?? endIndex
        return self[index ..< end]
      }
  }
}

print("Broken")
print([1,2,3,4,5,6,7,8,9,10].chunked_broken(into: 2))
print([1,2,3,4,5,6,7,8,9,10].lazy.filter { $0 % 2 == 0 }.chunked_broken(into: 2).map { Array($0) })


extension Collection {
  public func chunked_consumer(into size: Int) -> [SubSequence] {
    var chunks: [SubSequence] = []
    var rest = self[...]
    while !rest.isEmpty {
      chunks.append(rest.prefix(size))
      rest = rest.dropFirst(size)
    }
    return chunks
  }
}

print("Consuming")
print([1,2,3,4,5,6,7,8,9,10].chunked_consumer(into: 2))
print([1,2,3,4,5,6,7,8,9,10].lazy.filter { $0 % 2 == 0 }.chunked_consumer(into: 2).map { Array($0) })

The prefix/dropFirst combo is the sort of thing discussed here under "Collection Consumers".

2 Likes