Arrays 在两个元素的数组中拆分大数组

Arrays 在两个元素的数组中拆分大数组,arrays,swift,slice,Arrays,Swift,Slice,我有一个很大的对象列表,我需要将它们拆分为一组两个元素,用于UI propouse 例如: [0,1,2,3,4,5,6] 成为包含这四个数组的数组 [[0,1]、[2,3]、[4,5]、[6]] 拆分数组的方法有很多种。但是,如果阵列很大,什么是最有效的(成本最低的)。如果您想提高效率,可以采用一种方法,以惰性方式生成每个包含2个元素的阵列,这样您一次只能在内存中存储2个元素: public struct ChunkGen<G : GeneratorType> : Generato

我有一个很大的对象列表,我需要将它们拆分为一组两个元素,用于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, 2, 3, 4, 5].chunk(2).generate()

g.next() // [1, 2]
g.next() // [3, 4]
g.next() // [5]
g.next() // nil
对于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, n: n)
  }
}

var g = [1, 2, 3, 4, 5].chunk(2).makeIterator()

g.next() // [1, 2]
g.next() // [3, 4]
g.next() // [5]
g.next() // nil
公共结构ChunkIterator:IteratorProtocol{ fileprivate变量i:i fileprivate let n:Int public mutating func next()->[I.Element]{ guard let head=i.next()else{return nil} var build=[head] 建设储备能力(n) 对于(1..ChunkIterator)中的uu{ 返回ChunkIterator(i:seq.makeIterator(),n:n) } } 公共扩展序列{ func chunk(n:Int)->ChunkSeq{ 返回ChunkSeq(seq:self,n:n) } } var g=[1,2,3,4,5].chunk(2).makeIterator() g、 next()/[1,2] g、 next()/[3,4] g、 下一步()/[5] g、 next()//nil 您可以使用的Aweasome框架。有
chunk
功能,它可以完全满足您的需要:

[1, 2, 3, 4, 5].chunk(2)

[[1, 2], [3, 4], [5]]
此外,还有很多用于序列的函数,您一定要查看它


您可以看看他对
chunk
(它使用生成器)的实现也许不是最有效的解决方案,但却是最直接的解决方案:

func toPairs(numbers:[Int])->[[Int]]
{
    var pairs:[[Int]]=[]
    var pair:[Int]=[]
    for var index=0;index<numbers.count;index++ {
        pair.append(numbers[index])
        if pair.count == 2 || index==numbers.count-1 {
            pairs.append(pair)
            pair=[]
        }
    }
    return pairs
}

var numbers=[0,1,2,3,4,5]

var pairs=toPairs(numbers)

print(pairs)

或者,您可以使用
reduce
,但这可能不是最有效的:

let res = a.reduce([[Int]]()) { (var acc: [[Int]], current: Int) in

    if acc.last != nil && acc.last?.count < 2 {
        var newLast = acc.last
        newLast?.append(current)
        acc.removeLast()

        acc.append(newLast!)
    } else {
        acc.append([current])
    }
    return acc
}
let res=a.reduce([[Int]]){(var acc:[[Int]],current:Int)in
如果acc.last!=零和acc.last?计数<2{
var newLast=附件last
newLast?.append(当前)
附件:removeLast()
acc.append(newLast!)
}否则{
acc.append([当前])
}
返回acc
}

如果你想要一个子片数组,你可以使用
split
函数来生成它,使用一个闭包来捕获状态变量并在它通过每个元素时递增,只在每个第n个元素上分裂。作为
Sliceable
的扩展(仅限于Swift 2.0,在1.2中需要是一个自由函数):

子片非常有效,因为它们通常与原始的可切片实体共享内部存储。因此,不会分配新内存来存储元素-只有用于跟踪子片指针到原始数组的内存

注意,这将适用于任何可切片的对象,例如字符串:

"Hello, I must be going"
    .characters
    .splitEvery(3)
    .map(String.init)
返回
[“He”、“lo”、“I”、“mu”、“t”、“e”、“oi”、“g”]

如果您想将阵列延迟拆分(即生成一个仅按需提供子片的序列),可以使用
anyGenerator
编写该序列:

extension Sliceable {
    func lazilySplitEvery(n: Index.Distance) -> AnySequence<SubSlice> {

        return AnySequence { () -> AnyGenerator<SubSlice> in
            var i: Index = self.startIndex
            return anyGenerator {
                guard i != self.endIndex else { return nil }
                let j = advance(i, n, self.endIndex)
                let r = i..<j
                i = j
                return self[r]
            }
        }
    }
}


for x in [1,2,3,4,5,6,7].lazilySplitEvery(3) {
    print(x)
}
// prints [1, 2, 3]
//        [4, 5, 6]
//        [7]
可分片扩展{
func lazlysplitevery(n:Index.Distance)->AnySequence{
返回任意序列{()->中的任意生成器
变量i:索引=self.startIndex
返回任意生成器{
guard i!=self.endIndex else{return nil}
设j=advance(i,n,self.endIndex)
设r=i..swift2

让arr=[1,2,3,4,5,6,7,8,9,10,11,12]
扩展阵列{
func splitBy(子集:Int)->[[Element]]{
返回0.stride(to:self.count,by:subSize).map{startIndex in
让endIndex=startIndex.advancedBy(子版,限制:self.count)
返回数组(自[startIndex..
到目前为止,我看到的最短解决方案(Swift 4)来自:

扩展数组{
func块(chunkSize:Int)->[[Element]]{
返回步幅(从:0到:self.count,按:chunkSize)。映射{

数组(self[$0..我没有测试效率,但这包含了一个可能的解决方案:。请参阅@heapach:我认为Swift编译器不接受Java源代码:)哦,sry..查看标记可能会有所帮助:-DSee显示了5种不同的方法来解决您的问题。在没有协议扩展的情况下,我如何在Swift 1.2中使用它?
extension Sliceable {
    func splitEvery(n: Index.Distance) -> [SubSlice] {
        var i: Index.Distance = 0
        return split(self) { _ in ++i % n == 0 }
    }
}
"Hello, I must be going"
    .characters
    .splitEvery(3)
    .map(String.init)
extension Sliceable {
    func lazilySplitEvery(n: Index.Distance) -> AnySequence<SubSlice> {

        return AnySequence { () -> AnyGenerator<SubSlice> in
            var i: Index = self.startIndex
            return anyGenerator {
                guard i != self.endIndex else { return nil }
                let j = advance(i, n, self.endIndex)
                let r = i..<j
                i = j
                return self[r]
            }
        }
    }
}


for x in [1,2,3,4,5,6,7].lazilySplitEvery(3) {
    print(x)
}
// prints [1, 2, 3]
//        [4, 5, 6]
//        [7]
let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

extension Array {
    func splitBy(subSize: Int) -> [[Element]] {
        return 0.stride(to: self.count, by: subSize).map { startIndex in
            let endIndex = startIndex.advancedBy(subSize, limit: self.count)
            return Array(self[startIndex ..< endIndex])
        }
    }
}

let chunks = arr.splitBy(5)

print(chunks) // [[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12]]
extension Array {

    func chunks(chunkSize: Int) -> [[Element]] {
        return stride(from: 0, to: self.count, by: chunkSize).map {
            Array(self[$0..<Swift.min($0 + chunkSize, self.count)])
        }
    }

}