一个想法的演变...
首先,解决2D数组的问题:
如果你知道你的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()
,直到最终得到不是数组的值。如果该元素是非数组元素,则将其替换为迭代器提供的序列(或第二个数组)中按顺序提供元素的下一个值。我们使用
compactMap
而不是
map
来处理
iter.next()
返回可选值的事实,因为它可能用完值,在这种情况下,
remap()
将替换剩余元素为
nil
,同时仍保持第一个嵌套数组的结构。
示例:
// 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], [], [[]]]
[[Int]]
吗?这两个数组的基本元素数量是否相同? - vacawamaNumberFormatter
将数字字符串匹配为整数。 - koropok