2016-03-16 92 views
0

我试图从一个循环内的数组中获取一批3。我觉得Swift必须有更优雅的方式。在Swift中从数组中获取N个批次的N?

这是我到目前为止有:

for (index, item) in allItems.enumerate() { 
    var batch: [MyType] = [] 

    if index < allItems.endIndex { 
     batch.append(allItems[index]) 
    } 

    if index + 1 < allItems.endIndex { 
     batch.append(allItems[index + 1]) 
    } 

    if index + 2 < allItems.endIndex { 
     batch.append(allItems[index + 2]) 
    } 

    sendBatchSomewhere(batch) 
} 

任何更好,更安全的方式来实现抓一批?中间很容易,但当然处理开始和结束会有点棘手。任何Swifty的想法?

更新:

谢谢,这个精美的作品!这里的操场版本:

import Foundation 

typealias MyType = (a: String, b: Int, c: Int) 

let allItems1: [MyType] = [] 

let allItems2 = [ 
    (a: "Item 1", b: 2, c: 3) 
] 

let allItems3 = [ 
    (a: "Item 1", b: 2, c: 3), 
    (a: "Item 2", b: 4, c: 5), 
    (a: "Item 3", b: 6, c: 7), 
    (a: "Item 4", b: 8, c: 9), 
    (a: "Item 5", b: 10, c: 11), 
    (a: "Item 6", b: 12, c: 13), 
    (a: "Item 7", b: 14, c: 15), 
    (a: "Item 8", b: 16, c: 17), 
    (a: "Item 9", b: 18, c: 19), 
    (a: "Item 10", b: 20, c: 21), 
    (a: "Item 11", b: 22, c: 23) 
] 

let testItems = allItems3 // Change to allItems1, allItems2, allItems3, etc 
let batchSize = 3 

let output = testItems.indices.map { fromIndex -> [MyType] in 
    let toIndex = fromIndex.advancedBy(batchSize, limit: testItems.endIndex) 
    return Array(testItems[fromIndex ..< toIndex]) 
} 

print(output) => 

    [ 
     [("Item 1", 2, 3), ("Item 2", 4, 5), ("Item 3", 6, 7)], 
     [("Item 2", 4, 5), ("Item 3", 6, 7), ("Item 4", 8, 9)], 
     [("Item 3", 6, 7), ("Item 4", 8, 9), ("Item 5", 10, 11)], 
     [("Item 4", 8, 9), ("Item 5", 10, 11), ("Item 6", 12, 13)], 
     [("Item 5", 10, 11), ("Item 6", 12, 13), ("Item 7", 14, 15)], 
     [("Item 6", 12, 13), ("Item 7", 14, 15), ("Item 8", 16, 17)], 
     [("Item 7", 14, 15), ("Item 8", 16, 17), ("Item 9", 18, 19)], 
     [("Item 8", 16, 17), ("Item 9", 18, 19), ("Item 10", 20, 21)], 
     [("Item 9", 18, 19), ("Item 10", 20, 21), ("Item 11", 22, 23)], 
     [("Item 10", 20, 21), ("Item 11", 22, 23)], 
     [("Item 11", 22, 23)] 
    ] 
+0

是不是故意的,你的“批次”交叠? –

+0

好点,其实。建立手表并发症,因此批次中的第一项是“父母”。然后父母+ 1将成为下一批的父母。 – TruMan1

回答

3

您可以使用切片和advancedBy() ,这需要限制参数的三参数形式。 例子:

let allItems = [1, 2, 3, 4, 5] 
let batchSize = 3 

allItems.indices.forEach { fromIndex in 
    let toIndex = fromIndex.advancedBy(batchSize, limit: allItems.endIndex) 
    let batch = allItems[fromIndex ..< toIndex] 

    // Or, if you need a "real" array: 
    // let batch = Array(allItems[fromIndex ..< toIndex]) 

    print(batch) 
} 

输出:

 
[1, 2, 3] 
[2, 3, 4] 
[3, 4, 5] 
[4, 5] 
[5] 

如果你想与所有批次的数组,那么你可以使用map() 代替forEach()

let output = allItems.indices.map { fromIndex -> [Int] in 
    let toIndex = fromIndex.advancedBy(batchSize, limit: allItems.endIndex) 
    return Array(allItems[fromIndex ..< toIndex]) 
} 
print(output) 

输出:

 
[[1, 2, 3], [2, 3, 4], [3, 4, 5], [4, 5], [5]] 
+0

确实很高雅,再次感谢马丁!我从你的回答中用操场版更新了我的帖子。 – TruMan1

0

希望你找这个

var batch = allItems[0..<allItems.endIndex] + allItems[0..<allItems.endIndex-1] + allItems[0..<allItems.endIndex-2] 
    sendBatchSomewhere(batch) 
1

下面是一个扩展的方法(应该是安全的为好)应该是可重复使用的任何地方:

extension Array { 

    func getSubArray(startIndex: Int, maxNumber: Int) -> Array? { 

     guard startIndex < count else{ 
      return nil 
     } 
     let desiredLastIndex = startIndex + maxNumber 
     let endNumber = (desiredLastIndex >= endIndex) ? endIndex : desiredLastIndex 

     return Array(self[startIndex..<endNumber]) 
    } 
}