Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 斯威夫特:分割[String]的正确方法是什么,从而得到具有给定子数组大小的[[String]]?_Ios_Swift_Algorithm - Fatal编程技术网

Ios 斯威夫特:分割[String]的正确方法是什么,从而得到具有给定子数组大小的[[String]]?

Ios 斯威夫特:分割[String]的正确方法是什么,从而得到具有给定子数组大小的[[String]]?,ios,swift,algorithm,Ios,Swift,Algorithm,从一个大的[String]和一个给定的子数组大小开始,我可以用什么方法将这个数组拆分成更小的数组?(最后一个阵列将小于给定的子阵列大小) 具体示例: 拆分[“1”、“2”、“3”、“4”、“5”、“6”、“7”],最大拆分大小为2 该代码将产生[“1”、“2”]、[“3”、“4”]、[“5”、“6”]、[“7”]] 显然,我可以更手动地完成这项工作,但我觉得在swift中,像map()或reduce()这样的东西可以很好地完成我想要的工作。我认为您不会想使用map或reduce。Map用于对数组

从一个大的[String]和一个给定的子数组大小开始,我可以用什么方法将这个数组拆分成更小的数组?(最后一个阵列将小于给定的子阵列大小)

具体示例:

拆分[“1”、“2”、“3”、“4”、“5”、“6”、“7”],最大拆分大小为2

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


显然,我可以更手动地完成这项工作,但我觉得在swift中,像map()或reduce()这样的东西可以很好地完成我想要的工作。

我认为您不会想使用map或reduce。Map用于对数组中的每个元素应用函数,reduce用于展平数组。您要做的是将阵列切片为特定大小的子阵列。此代码段使用切片

var arr = ["1","2","3","4","5","6","7"]
var splitSize = 2

var newArr = [[String]]()
var i = 0
while i < arr.count {
    var slice: Slice<String>!
    if i + splitSize >= arr.count {
        slice = arr[i..<arr.count]
    }
    else {
        slice = arr[i..<i+splitSize]
    }
    newArr.append(Array(slice))
    i += slice.count
}
println(newArr)
var arr=[“1”、“2”、“3”、“4”、“5”、“6”、“7”]
var splitSize=2
var newArr=[[String]]()
变量i=0
当我在数的时候{
变量切片:切片!
如果i+splitSize>=arr.count{

slice=arr[i..我不会说它漂亮,但这里有一个使用
map
的方法:

let numbers = ["1","2","3","4","5","6","7"]
let splitSize = 2
let chunks = numbers.startIndex.stride(to: numbers.count, by: splitSize).map {
  numbers[$0 ..< $0.advancedBy(splitSize, limit: numbers.endIndex)]
}

上面这句话很切肤之痛,但它让我头疼。我不得不回到不那么快的方式

适用于Swift 2.0

var chunks = [[Int]]()
var temp = [Int]()
var splitSize = 3

var x = [1,2,3,4,5,6,7]

for (i, element) in x.enumerate() {

    if temp.count < splitSize {
        temp.append(element)
    }
    if temp.count == splitSize {
        chunks.append(temp)
        temp.removeAll()
    }
}

if !temp.isEmpty {
    chunks.append(temp)
}
var chunks=[[Int]]()
变量温度=[Int]()
var splitSize=3
变量x=[1,2,3,4,5,6,7]
对于x.enumerate()中的(i,元素){
如果温度计数

操场结果[[1,2,3],[4,5,6],[7]

我喜欢内特·库克的答案,看起来斯威夫特自编写以来已经有所进步,以下是我对数组的扩展:

extension Array {
    func chunk(chunkSize : Int) -> Array<Array<Element>> {
        return 0.stride(to: self.count, by: chunkSize)
            .map { Array(self[$0..<$0.advancedBy(chunkSize, limit: self.count)]) }
    }
}

使用Swift 5,根据您的需要,您可以选择以下五种方法之一来解决您的问题


1.在
集合
扩展方法中使用
AnyIterator
迭代符合
集合
协议的对象索引以返回此对象的子序列是一个很好的选择。在
集合
协议扩展中,可以通过以下实现声明
分块(by:)
方法:

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)
    }
    
}
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
    }
    
}
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)
        }
    }
    
}
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
    }
    
}
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])
    }
    
}

2.在
数组
扩展方法中使用
stride(from:to:by:)
函数
Array
索引属于
Int
类型,并且符合
可移动的
协议。因此,您可以使用和与它们一起使用。在
数组
扩展中,您可以通过以下实现声明
分块(by:)
方法:

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)
    }
    
}
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
    }
    
}
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)
        }
    }
    
}
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
    }
    
}
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])
    }
    
}

3.在
数组
扩展方法中使用递归方法 基于Nate Cook,您可以使用以下实现在
数组
扩展中声明
chunked(by:)
方法:

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)
    }
    
}
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
    }
    
}
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)
        }
    }
    
}
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
    }
    
}
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])
    }
    
}

4.在
集合中使用for循环和批处理
扩展方法 Chris Eidhof和Florian Kugler在视频中演示了如何使用简单的for循环填充一批序列元素,并在完成后将它们附加到数组中。在
序列
扩展中,您可以通过以下实现声明
分块(by:)
方法:

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)
    }
    
}
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
    }
    
}
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)
        }
    }
    
}
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
    }
    
}
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 newArray = array.chunked(by: 2)
print(newArray) // prints: [["1", "2"], ["3", "4"], ["5", "6"], ["7", "8"], ["9"]]
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"]]
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"]]
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"]]
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"]]
let result = [1,2,3,4,5,6,7,8,9].eachSlice(2)
// [[1, 2], [3, 4], [5, 6], [7, 8], [9]]

5.使用符合
顺序
迭代协议
的自定义
结构
如果不想创建
序列
集合
数组
的扩展,可以创建符合
序列
迭代协议的自定义
结构
。此
结构应具有以下实现:

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)
    }
    
}
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
    }
    
}
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)
        }
    }
    
}
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
    }
    
}
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])
    }
    
}

在这里,我将用另一个基于
AnyGenerator的实现来说明问题。

extension Array {
    func chunks(_ size: Int) -> AnyIterator<[Element]> {
        if size == 0 {
            return AnyIterator {
                return nil
            }
        }

        let indices = stride(from: startIndex, to: count, by: size)
        var generator = indices.makeIterator()

        return AnyIterator {
            guard let i = generator.next() else {
                return nil
            }

            var j = self.index(i, offsetBy: size)
            repeat {
                j = self.index(before: j)
            } while j >= self.endIndex

            return self[i...j].lazy.map { $0 }
        }
    }
}
结果:

[["1", "2"], ["3", "4"], ["5", "6"], ["7"]]

在Swift 3/4中,如下所示:

让数字=[“1”、“2”、“3”、“4”、“5”、“6”、“7”]
让chunkSize=2
让chunks=stride(从:0到:numbers.count,按:chunkSize).map{
数组(数字[$0..[[Element]]{
返回步幅(从:0到:self.count,按:chunkSize)。映射{
数组(self[$0..可以表示为数组的扩展:

extension Array {
    func chunked(by chunkSize:Int) -> [[Element]] {
        let groups = stride(from: 0, to: self.count, by: chunkSize).map {
            Array(self[$0..<[$0 + chunkSize, self.count].min()!])
        }
        return groups
    }
}
扩展数组{
func chunked(按chunkSize:Int)->[[Element]]{
让组=步幅(从:0到:self.count,按:chunkSize).map{

数组(self[$0..您知道任何带有[a…b]swift样式的解决方案的运行速度都比普通解决方案慢10倍吗

for y in 0..<rows {
    var row = [Double]()
    for x in 0..<cols {
        row.append(stream[y * cols + x])
    }
    mat.append(row)
}

对于0中的y..Swift 4中的新增功能,您可以使用
reduce(into:)
高效地执行此操作。以下是序列的扩展:

extension Sequence {
    func eachSlice(_ clump:Int) -> [[Self.Element]] {
        return self.reduce(into:[]) { memo, cur in
            if memo.count == 0 {
                return memo.append([cur])
            }
            if memo.last!.count < clump {
                memo.append(memo.removeLast() + [cur])
            } else {
                memo.append([cur])
            }
        }
    }
}

在Swift 4或更高版本中,您还可以扩展
集合
并返回其
子序列的集合
,以便能够将其与
字符串协议
类型(
字符串
子字符串
)一起使用。这样,它将返回子字符串的集合,而不是一组字符的集合:

Xcode 10.1•Swift 4.2.1或更高版本

extension Collection {
    func subSequences(limitedTo maxLength: Int) -> [SubSequence] {
        precondition(maxLength > 0, "groups must be greater than zero")
        var start = startIndex
        var subSequences: [SubSequence] = []
        while start < endIndex {
            let end = index(start, offsetBy: maxLength, limitedBy: endIndex) ?? endIndex
            defer { start = end }
            subSequences.append(self[start..<end])
        }
        return subSequences
    }
}

数组或数组字符片

let chars = ["a","b","c","d","e","f","g","h","i"]
chars.singles  // [["a"], ["b"], ["c"], ["d"], ["e"], ["f"], ["g"], ["h"], ["i"]]
chars.pairs    // [["a", "b"], ["c", "d"], ["e", "f"], ["g", "h"], ["i"]]
chars.triples  // [["a", "b", "c"], ["d", "e", "f"], ["g", "h", "i"]]
chars.quads    // [["a", "b", "c", "d"], ["e", "f", "g", "h"], ["i"]]
chars.dropFirst(2).quads  // [["c", "d", "e", "f"], ["g", "h", "i"]]

StringProtocol元素(字符串和子字符串)

Swift 5.1-所有类型托收的通用解决方案:
扩展集合,其中索引==Int{
func chunked(按chunkSize:Int)->[[Element]]{
跨步(从:startIndex,到:endIndex,by:chunkSize).map{Array(self[$0..
public扩展名可选){
///根据条件将值包装在“可选”中。
///-参数:
///-wrapped:非可选值。
///-getIsNil:将导致“nil”的条件。
初始化(
_包好了,包好了,,
nilWhen getIsNil:(包装)抛出->Bool
)重演{
self=尝试获取零(已包装)?零:已包装
}
}
公共扩展序列{
///将“序列”分成相等的“块”。
///
///-参数