Estoy tratando de dividir la matriz en pares. Puedo dividir en pares consecutivos pero quiero dividir en pares que incluyan el valor anterior como se menciona en Resultados
Lógica para dividir en pares consecutivos, lo que probé.
extension Array { func chunks(_ chunkSize: Int) -> [[Element]] { return stride(from: 0, to: self.count, by: chunkSize).map { Array(self[$0..<Swift.min($0 + chunkSize, self.count)]) } }Formación:
["1", "2", "3", "4", "5", "6", "7", "8", "9"]Resultados:
[["1", "2"], ["2", "3"], ["3", "4"], ["4", "5"], ["6", "7"], ["7", "8"], ["8", "9"]]Qué tal esto:
let a = [ 1, 2, 3, 4, 5, 6, 7, 8, 9] let pairs = Array(zip(a, a.dropFirst())).map {[$0.0, $0.1] } print(pairs)que salidas
[[1, 2], [2, 3], [3, 4], [4, 5], [5, 6], [6, 7], [7, 8], [8, 9]]
Si desea un tamaño de fragmento arbitrario, puede escribir la extensión de esta manera:
extension Array { func chunks(_ chunkSize: Int, includePartialChunk: Bool = true) -> [[Element]] { var indexes = Array<Int>(stride(from: 0, to: count, by: chunkSize - 1)) if includePartialChunk, let last = indexes.last, last < count - 1 { indexes.append(count-1) } return zip(indexes, indexes.dropFirst()).map {Array(self[$0.0...$0.1])} } } Utilice el parámetro includePartialChunk para decirle a la función si desea incluir un "fragmento parcial" al final cuando el tamaño de la matriz no es un múltiplo par del tamaño del fragmento. Si es verdadero (el valor predeterminado), devuelve un último fragmento que es más pequeño que chunkSize pero va al final de la matriz. Si es falso, solo devuelve fragmentos de tamaño completo, pero omitirá los elementos de la matriz al final que no caben en un fragmento de tamaño completo.
(Tendré que estudiar la versión UnfoldSequence de Leo y ver si puedo adaptar mi código a eso).
No es una respuesta directa a la pregunta, pero los elementos de la secuencia deben calcularse con pereza. Debe usar el tipo Swift UnfoldSequence de la siguiente manera:
extension Collection { var unfoldedNeighbors: UnfoldSequence<SubSequence,Index> { sequence(state: startIndex) { start in guard start < endIndex else { return nil } guard let end = index(start, offsetBy: 2, limitedBy: endIndex) else { return nil } defer { formIndex(after: &start) } return self[start..<end] } } var neighborsSubsequences: [SubSequence] { .init(unfoldedNeighbors) } var neighborsArrays: [[Element]] { unfoldedNeighbors.map([Element].init) } }Uso:
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9] for neighbors in numbers.unfoldedNeighbors { print(neighbors) }Si necesitas controlar el número de elementos de cada subsecuencia y también si incluye la cola o no:
extension Collection { func unfoldedNeighbors(limitedTo length: Int, includesTail: Bool = false) -> UnfoldSequence<SubSequence,Index> { sequence(state: startIndex) { start in guard start < endIndex else { return nil } guard let end = index(start, offsetBy: length, limitedBy: endIndex) else { if includesTail { defer { formIndex(&start, offsetBy: length-1, limitedBy: endIndex) } return self[start...] } return nil } defer { formIndex(&start, offsetBy: length-1, limitedBy: endIndex) } return self[start..<end] } } func neighborsSequences(limitedTo length: Int, includesTail: Bool = false) -> [SubSequence] { .init(unfoldedNeighbors(limitedTo: length, includesTail: includesTail)) } func neighborsArrays(limitedTo length: Int, includesTail: Bool = false) -> [[Element]] { unfoldedNeighbors(limitedTo: length, includesTail: includesTail).map([Element].init) } }Uso:
let numbers = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] for neighbors in numbers.unfoldedNeighbors(limitedTo: 3, includesTail: true) { print(neighbors) }Esto imprimirá:
[1, 2, 3]
[3, 4, 5]
[5, 6, 7]
[7, 8, 9]
[9, 10]
let neighborsSequences = a.neighborsSequences(limitedTo: 3, includesTail: true) // [[1, 2, 3], [3, 4, 5], [5, 6, 7], [7, 8, 9], [9, 10]] of type [Array<Int>.SubSequence] let neighborsArrays = a.neighborsArrays(limitedTo: 3, includesTail: true) // [[1, 2, 3], [3, 4, 5], [5, 6, 7], [7, 8, 9], [9, 10]] of type [[Int]]