3 回答

TA貢獻(xiàn)1712條經(jīng)驗 獲得超3個贊
在Swift 3/4中,其外觀如下所示:
let numbers = ["1","2","3","4","5","6","7"]
let chunkSize = 2
let chunks = stride(from: 0, to: numbers.count, by: chunkSize).map {
Array(numbers[$0..<min($0 + chunkSize, numbers.count)])
}
// prints as [["1", "2"], ["3", "4"], ["5", "6"], ["7"]]
作為Array的擴(kuò)展:
extension Array {
func chunked(by chunkSize: Int) -> [[Element]] {
return stride(from: 0, to: self.count, by: chunkSize).map {
Array(self[$0..<Swift.min($0 + chunkSize, self.count)])
}
}
}
或者稍微冗長一些,但更籠統(tǒng):
let numbers = ["1","2","3","4","5","6","7"]
let chunkSize = 2
let chunks: [[String]] = stride(from: 0, to: numbers.count, by: chunkSize).map {
let end = numbers.endIndex
let chunkEnd = numbers.index($0, offsetBy: chunkSize, limitedBy: end) ?? end
return Array(numbers[$0..<chunkEnd])
}
這是更一般的,因為我對集合中索引的類型做出的假設(shè)較少。在以前的實現(xiàn)中,我假設(shè)可以對它們進(jìn)行比較和添加。
請注意,在Swift 3中,高級索引的功能已從索引本身轉(zhuǎn)移到集合中。

TA貢獻(xiàn)1860條經(jīng)驗 獲得超9個贊
使用Swift 5,您可以根據(jù)需要選擇以下五種方法之一來解決問題。
1. AnyIterator在Collection擴(kuò)展方法中使用
AnyIterator是迭代符合Collection協(xié)議的對象索引以返回該對象的子序列的一個不錯的選擇。在Collection協(xié)議擴(kuò)展中,可以chunked(by:)使用以下實現(xiàn)聲明方法:
extension Collection {
func chunked(by distance: Int) -> [[Element]] {
precondition(distance > 0, "distance must be greater than 0") // prevents infinite loop
var index = startIndex
let iterator: AnyIterator<Array<Element>> = AnyIterator({
let newIndex = self.index(index, offsetBy: distance, limitedBy: self.endIndex) ?? self.endIndex
defer { index = newIndex }
let range = index ..< newIndex
return index != self.endIndex ? Array(self[range]) : nil
})
return Array(iterator)
}
}
用法:
let array = ["1", "2", "3", "4", "5", "6", "7", "8", "9"]
let newArray = array.chunked(by: 2)
print(newArray) // prints: [["1", "2"], ["3", "4"], ["5", "6"], ["7", "8"], ["9"]]
2. stride(from:to:by:)在Array擴(kuò)展方法中使用功能
Array索引的類型Int并符合Strideable協(xié)議。因此,您可以stride(from:to:by:)與和advanced(by:)一起使用。在Array擴(kuò)展中,您可以chunked(by:)使用以下實現(xiàn)聲明方法:
extension Array {
func chunked(by distance: Int) -> [[Element]] {
let indicesSequence = stride(from: startIndex, to: endIndex, by: distance)
let array: [[Element]] = indicesSequence.map {
let newIndex = $0.advanced(by: distance) > endIndex ? endIndex : $0.advanced(by: distance)
//let newIndex = self.index($0, offsetBy: distance, limitedBy: self.endIndex) ?? self.endIndex // also works
return Array(self[$0 ..< newIndex])
}
return array
}
}
用法:
let array = ["1", "2", "3", "4", "5", "6", "7", "8", "9"]
let newArray = array.chunked(by: 2)
print(newArray) // prints: [["1", "2"], ["3", "4"], ["5", "6"], ["7", "8"], ["9"]]
3.在Array擴(kuò)展方法中使用遞歸方法
基于Nate Cook 遞歸代碼,您可以使用以下實現(xiàn)chunked(by:)在Array擴(kuò)展中聲明一個方法:
extension Array {
func chunked(by distance: Int) -> [[Element]] {
precondition(distance > 0, "distance must be greater than 0") // prevents infinite loop
if self.count <= distance {
return [self]
} else {
let head = [Array(self[0 ..< distance])]
let tail = Array(self[distance ..< self.count])
return head + tail.chunked(by: distance)
}
}
}
用法:
let array = ["1", "2", "3", "4", "5", "6", "7", "8", "9"]
let newArray = array.chunked(by: 2)
print(newArray) // prints: [["1", "2"], ["3", "4"], ["5", "6"], ["7", "8"], ["9"]]
4.在Collection擴(kuò)展方法中使用for循環(huán)和批處理
克里斯·艾德霍夫(Chris Eidhof)和弗洛里安·庫格勒(Florian Kugler)在Swift Talk#33-Sequence&Iterator(Collections#2)視頻中展示了如何使用簡單的for循環(huán)填充一批序列元素,并在完成時將它們附加到數(shù)組中。在Sequence擴(kuò)展中,您可以chunked(by:)使用以下實現(xiàn)聲明方法:
extension Collection {
func chunked(by distance: Int) -> [[Element]] {
var result: [[Element]] = []
var batch: [Element] = []
for element in self {
batch.append(element)
if batch.count == distance {
result.append(batch)
batch = []
}
}
if !batch.isEmpty {
result.append(batch)
}
return result
}
}
用法:
let array = ["1", "2", "3", "4", "5", "6", "7", "8", "9"]
let newArray = array.chunked(by: 2)
print(newArray) // prints: [["1", "2"], ["3", "4"], ["5", "6"], ["7", "8"], ["9"]]
5.使用struct符合Sequence和IteratorProtocol協(xié)議的習(xí)慣
如果你不希望創(chuàng)建的擴(kuò)展Sequence,Collection或者Array,你可以創(chuàng)建自定義struct符合Sequence和IteratorProtocol協(xié)議。這struct應(yīng)該具有以下實現(xiàn):
struct BatchSequence<T>: Sequence, IteratorProtocol {
private let array: [T]
private let distance: Int
private var index = 0
init(array: [T], distance: Int) {
precondition(distance > 0, "distance must be greater than 0") // prevents infinite loop
self.array = array
self.distance = distance
}
mutating func next() -> [T]? {
guard index < array.endIndex else { return nil }
let newIndex = index.advanced(by: distance) > array.endIndex ? array.endIndex : index.advanced(by: distance)
defer { index = newIndex }
return Array(array[index ..< newIndex])
}
}
用法:
let array = ["1", "2", "3", "4", "5", "6", "7", "8", "9"]
let batchSequence = BatchSequence(array: array, distance: 2)
let newArray = Array(batchSequence)
print(newArray) // prints: [["1", "2"], ["3", "4"], ["5", "6"], ["7", "8"], ["9"]]
- 3 回答
- 0 關(guān)注
- 881 瀏覽
添加回答
舉報