Эволюция идеи ...
Во-первых, решение для двумерного массива:
Если вы знаете свой array1
- это двумерный массив (массив массивов элементов), вы можете сделать это, превратив array2
в итератор и используя map
и compactMap
для замены элементов:
let array1 = [[1,2,3],[4,5,6]]
let array2 = ["one","two","three","four","five","six"]
var iter = array2.makeIterator()
let array3 = array1.map { arr in arr.compactMap { _ in iter.next() }}
print(array3)
Результат:
[["one", "two", "three"], ["four", "five", "six"]]
Более общее и общее решение:
Вот более общеерешение, которое использует последовательность вместо array2
, которое не зависит от того, заранее ли вы знаете макет array1
или типы значений массива или последовательности:
func remap<S: Sequence>(_ array: [Any], using sequence: S) -> [Any] {
var iter = sequence.makeIterator()
func remap(_ array: [Any]) -> [Any] {
return array.compactMap { value in
if let subarray = value as? [Any] {
return remap(subarray)
} else {
return iter.next()
}
}
}
return remap(array)
}
Как это работает:
Второй массив или последовательность превращается в итератор с именем iter
, который позволяет нам получать значения по порядку при повторных вызовах iter.next()
.
Затем вторая рекурсивная версия remap()
используется для преобразования [Any]
в [Any]
в порядке обхода в глубину.compactMap()
используется для замены элементов массива.При замене элементов массива, если этот элемент является другим массивом, он рекурсивно вызывает remap()
для этого массива, пока он, наконец, не достигнет значений, которые не являются массивами.Если элемент не является элементом массива, он заменяет его значением next
от итератора, который обслуживает элементы последовательности (или второго массива) по порядку.Мы используем compactMap
вместо map
для обработки того факта, что iter.next()
возвращает необязательные значения, потому что у него могут заканчиваться значения, и в этом случае он возвращает nil
.В этом случае remap()
заменит оставшиеся элементы ничем, при этом сохраняя структуру первого вложенного массива.
Примеры:
// replace Ints with Strings
let array1: [Any] = [1, [2, 3], [4, [5, 6]]]
let array2 = ["one","two","three","four","five","six"]
let array3 = remap(array1, using: array2)
print(array3)
["one", ["two", "three"], ["four", ["five", "six"]]]
// replace Strings with Ints
let array4: [Any] = ["a", ["b", "c"], [[["d"]], "e"]]
let array5 = [1, 2, 3, 4, 5]
let array6 = remap(array4, using: array5)
print(array6)
[1, [2, 3], [[[4]], 5]]
// map letters to numbers starting with 5 using a partial range
print(remap(["a", ["b"], ["c", ["d"]]], using: 5...))
[5, [6], [7, [8]]]
// using stride to create a sequence of even numbers
let evens = stride(from: 2, to: Int.max, by: 2)
print(remap([["a", "b"], ["c"], [["d"]]], using: evens))
[[2, 4], [6], [[8]]]
// an example of not enough values in replacement array
print(remap([["a", "b"], ["c"], [["d"]]], using: [1]))
[[1], [], [[]]]