我有大量的对象列表,我需要将它们分成一组两个元素用于UI propouse.
例:
[0,1,2,3,4,5,6]
成为这四个数组的数组
[[0,1],[2,3],[4,5],[6]]
分割阵列有很多种方法.但是,如果阵列很大,那么效率最高(成本最低)的是什么.
如果你正在寻找效率,你可以有一个方法,可以懒惰地生成每个2个元素的数组,所以你一次只能在内存中存储2个元素:
- public struct ChunkGen<G : GeneratorType> : GeneratorType {
- private var g: G
- private let n: Int
- private var c: [G.Element]
- public mutating func next() -> [G.Element]? {
- var i = n
- return g.next().map {
- c = [$0]
- while --i > 0,let next = g.next() { c.append(next) }
- return c
- }
- }
- private init(g: G,n: Int) {
- self.g = g
- self.n = n
- self.c = []
- self.c.reserveCapacity(n)
- }
- }
- public struct ChunkSeq<S : SequenceType> : SequenceType {
- private let seq: S
- private let n: Int
- public func generate() -> ChunkGen<S.Generator> {
- return ChunkGen(g: seq.generate(),n: n)
- }
- }
- public extension SequenceType {
- func chunk(n: Int) -> ChunkSeq<Self> {
- return ChunkSeq(seq: self,n: n)
- }
- }
- var g = [1,5].chunk(2).generate()
- g.next() // [1,2]
- g.next() // [3,4]
- g.next() // [5]
- g.next() // nil
此方法适用于任何SequenceType,而不仅仅是Arrays.
对于Swift 1,没有协议扩展,你有:
- public struct ChunkGen<T> : GeneratorType {
- private var (st,en): (Int,Int)
- private let n: Int
- private let c: [T]
- public mutating func next() -> ArraySlice<T>? {
- (st,en) = (en,en + n)
- return st < c.endIndex ? c[st..<min(en,c.endIndex)] : nil
- }
- private init(c: [T],n: Int) {
- self.c = c
- self.n = n
- self.st = 0 - n
- self.en = 0
- }
- }
- public struct ChunkSeq<T> : SequenceType {
- private let c: [T]
- private let n: Int
- public func generate() -> ChunkGen<T> {
- return ChunkGen(c: c,n: n)
- }
- }
- func chunk<T>(ar: [T],#n: Int) -> ChunkSeq<T> {
- return ChunkSeq(c: ar,n: n)
- }
对于Swift 3:
- public struct ChunkIterator<I: IteratorProtocol> : IteratorProtocol {
- fileprivate var i: I
- fileprivate let n: Int
- public mutating func next() -> [I.Element]? {
- guard let head = i.next() else { return nil }
- var build = [head]
- build.reserveCapacity(n)
- for _ in (1..<n) {
- guard let x = i.next() else { break }
- build.append(x)
- }
- return build
- }
- }
- public struct ChunkSeq<S: Sequence> : Sequence {
- fileprivate let seq: S
- fileprivate let n: Int
- public func makeIterator() -> ChunkIterator<S.Iterator> {
- return ChunkIterator(i: seq.makeIterator(),n: n)
- }
- }
- public extension Sequence {
- func chunk(_ n: Int) -> ChunkSeq<Self> {
- return ChunkSeq(seq: self,5].chunk(2).makeIterator()
- g.next() // [1,4]
- g.next() // [5]
- g.next() // nil