Swift:将[String]拆分为给定子数组大小的[[String]]的正确方法是什么?

从较大的[String]和给定的子数组大小开始,将这个数组拆分为较小的数组的最佳方法是什么?(最后一个数组将小于给定的子数组大小)。


具体示例:


以最大分割尺寸2分割[“ 1”,“ 2”,“ 3”,“ 4”,“ 5”,“ 6”,“ 7”]


该代码将产生[[“ 1”,“ 2”],[“ 3”,“ 4”],[“ 5”,“ 6”],[“ 7”]]


显然,我可以手动进行一些操作,但是我觉得像map()或reduce()这样的快速操作可能确实可以实现我想要的效果。


阿波罗的战车
浏览 834回答 3
3回答

交互式爱情

在Swift 3/4中,其外观如下所示:let numbers = ["1","2","3","4","5","6","7"]let chunkSize = 2let chunks = stride(from: 0, to: numbers.count, by: chunkSize).map {&nbsp; &nbsp; Array(numbers[$0..<min($0 + chunkSize, numbers.count)])}// prints as [["1", "2"], ["3", "4"], ["5", "6"], ["7"]]作为Array的扩展:extension Array {&nbsp; &nbsp; func chunked(by chunkSize: Int) -> [[Element]] {&nbsp; &nbsp; &nbsp; &nbsp; return stride(from: 0, to: self.count, by: chunkSize).map {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Array(self[$0..<Swift.min($0 + chunkSize, self.count)])&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}或者稍微冗长一些,但更笼统:let numbers = ["1","2","3","4","5","6","7"]let chunkSize = 2let chunks: [[String]] = stride(from: 0, to: numbers.count, by: chunkSize).map {&nbsp; &nbsp; let end = numbers.endIndex&nbsp; &nbsp; let chunkEnd = numbers.index($0, offsetBy: chunkSize, limitedBy: end) ?? end&nbsp; &nbsp; return Array(numbers[$0..<chunkEnd])}这是更一般的,因为我对集合中索引的类型做出的假设较少。在以前的实现中,我假设可以对它们进行比较和添加。请注意,在Swift 3中,高级索引的功能已从索引本身转移到集合中。

慕码人2483693

使用Swift 5,您可以根据需要选择以下五种方法之一来解决问题。1. AnyIterator在Collection扩展方法中使用AnyIterator是迭代符合Collection协议的对象索引以返回该对象的子序列的一个不错的选择。在Collection协议扩展中,可以chunked(by:)使用以下实现声明方法:extension Collection {&nbsp; &nbsp; func chunked(by distance: Int) -> [[Element]] {&nbsp; &nbsp; &nbsp; &nbsp; precondition(distance > 0, "distance must be greater than 0") // prevents infinite loop&nbsp; &nbsp; &nbsp; &nbsp; var index = startIndex&nbsp; &nbsp; &nbsp; &nbsp; let iterator: AnyIterator<Array<Element>> = AnyIterator({&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let newIndex = self.index(index, offsetBy: distance, limitedBy: self.endIndex) ?? self.endIndex&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; defer { index = newIndex }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let range = index ..< newIndex&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return index != self.endIndex ? Array(self[range]) : nil&nbsp; &nbsp; &nbsp; &nbsp; })&nbsp; &nbsp; &nbsp; &nbsp; return Array(iterator)&nbsp; &nbsp; }}用法: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扩展方法中使用功能Array索引的类型Int并符合Strideable协议。因此,您可以stride(from:to:by:)与和advanced(by:)一起使用。在Array扩展中,您可以chunked(by:)使用以下实现声明方法:extension Array {&nbsp; &nbsp; func chunked(by distance: Int) -> [[Element]] {&nbsp; &nbsp; &nbsp; &nbsp; let indicesSequence = stride(from: startIndex, to: endIndex, by: distance)&nbsp; &nbsp; &nbsp; &nbsp; let array: [[Element]] = indicesSequence.map {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let newIndex = $0.advanced(by: distance) > endIndex ? endIndex : $0.advanced(by: distance)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //let newIndex = self.index($0, offsetBy: distance, limitedBy: self.endIndex) ?? self.endIndex // also works&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return Array(self[$0 ..< newIndex])&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; return array&nbsp; &nbsp; }}用法: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扩展方法中使用递归方法基于Nate Cook 递归代码,您可以使用以下实现chunked(by:)在Array扩展中声明一个方法:extension Array {&nbsp; &nbsp; func chunked(by distance: Int) -> [[Element]] {&nbsp; &nbsp; &nbsp; &nbsp; precondition(distance > 0, "distance must be greater than 0") // prevents infinite loop&nbsp; &nbsp; &nbsp; &nbsp; if self.count <= distance {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return [self]&nbsp; &nbsp; &nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let head = [Array(self[0 ..< distance])]&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let tail = Array(self[distance ..< self.count])&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return head + tail.chunked(by: distance)&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}用法: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扩展方法中使用for循环和批处理克里斯·艾德霍夫(Chris Eidhof)和弗洛里安·库格勒(Florian Kugler)在Swift Talk#33-Sequence&Iterator(Collections#2)视频中展示了如何使用简单的for循环填充一批序列元素,并在完成时将它们附加到数组中。在Sequence扩展中,您可以chunked(by:)使用以下实现声明方法:extension Collection {&nbsp; &nbsp; func chunked(by distance: Int) -> [[Element]] {&nbsp; &nbsp; &nbsp; &nbsp; var result: [[Element]] = []&nbsp; &nbsp; &nbsp; &nbsp; var batch: [Element] = []&nbsp; &nbsp; &nbsp; &nbsp; for element in self {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; batch.append(element)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if batch.count == distance {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; result.append(batch)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; batch = []&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; if !batch.isEmpty {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; result.append(batch)&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; return result&nbsp; &nbsp; }}用法: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协议的习惯如果你不希望创建的扩展Sequence,Collection或者Array,你可以创建自定义struct符合Sequence和IteratorProtocol协议。这struct应该具有以下实现:struct BatchSequence<T>: Sequence, IteratorProtocol {&nbsp; &nbsp; private let array: [T]&nbsp; &nbsp; private let distance: Int&nbsp; &nbsp; private var index = 0&nbsp; &nbsp; init(array: [T], distance: Int) {&nbsp; &nbsp; &nbsp; &nbsp; precondition(distance > 0, "distance must be greater than 0") // prevents infinite loop&nbsp; &nbsp; &nbsp; &nbsp; self.array = array&nbsp; &nbsp; &nbsp; &nbsp; self.distance = distance&nbsp; &nbsp; }&nbsp; &nbsp; mutating func next() -> [T]? {&nbsp; &nbsp; &nbsp; &nbsp; guard index < array.endIndex else { return nil }&nbsp; &nbsp; &nbsp; &nbsp; let newIndex = index.advanced(by: distance) > array.endIndex ? array.endIndex : index.advanced(by: distance)&nbsp; &nbsp; &nbsp; &nbsp; defer { index = newIndex }&nbsp; &nbsp; &nbsp; &nbsp; return Array(array[index ..< newIndex])&nbsp; &nbsp; }}用法: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"]]
打开App,查看更多内容
随时随地看视频慕课网APP