我正在尝试从循环中的数组中获取一批3。我觉得Swift必须有更优雅的方式。
这是我到目前为止所拥有的:
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)
}
任何更好,更安全的方法来获取批次?中间很容易,但当然处理开始和结束有点棘手。任何有趣的想法?
更新
谢谢,这很有效!这是游乐场版本:
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 :(得分: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]]
答案 1 :(得分: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])
}
}
答案 2 :(得分:0)
希望你能找到这个
var batch = allItems[0..<allItems.endIndex] + allItems[0..<allItems.endIndex-1] + allItems[0..<allItems.endIndex-2]
sendBatchSomewhere(batch)
答案 3 :(得分:0)
这是一个自定义的 ArrayIterator,它适用于我们的案例。也许对以后来这里的人有帮助
class ArrayIterator<T>{
private var array : [T] = []
private var stepSize: Int = 10
private var head: Int = 0
var hasNext: Bool {
get {
return head < array.count
}
}
class func from(array: [T], stepSize size: Int = 10, startingAt startIndex: Int = 0) -> ArrayIterator<T>{
let a = ArrayIterator<T>()
a.array = array
a.stepSize = size
a.head = startIndex
return a
}
func next() -> Array<T>? {
guard head < array.count else {
return nil
}
defer {
head = head + stepSize
}
guard stepSize < array.count else {
return array
}
if let _ = array[safe: (head + stepSize - 1)] {
return Array(array[head..<head + stepSize])
} else {
let remaider = (head + stepSize - 1) % array.count
return Array(array[head..<(head + stepSize - 1 - remaider)])
}
}
}