您说得对,对二维数组进行洗牌的一个好方法是展平它并对值进行洗牌。棘手的部分是如何将洗牌后的值恢复到数组的原始结构中。
通过将打乱的数组变成一个迭代器iter,我们可以调用iter.next()来获取每个值,并使用嵌套的maps来访问和替换原始值:
var arr = [[1], [2, 3], [4, 5, 6]]
var iter = arr.joined().shuffled().makeIterator()
let arr2 = arr.map { $0.map { _ in iter.next()! } }
print(arr2)
[[4], [5, 1], [3, 6, 2]]
将其变成通用函数:func shuffle2D<T>(_ arr: [[T]]) -> [[T]]
我们可以把它变成一个通用函数,可以打乱任何二维数组:
func shuffle2D<T>(_ arr: [[T]]) -> [[T]] {
var iter = arr.joined().shuffled().makeIterator()
return arr.map { $0.compactMap { _ in iter.next() }}
}
注意:我已将内部map 更改为compactMap,这样我们就可以避免强制解包iter.next()。
示例:
print(shuffle2D([[1, 2, 3], [4, 5, 6]]))
[[2, 5, 6], [3, 1, 4]]
print(shuffle2D([["a", "b"], ["c", "d"], ["e", "f"]]))
[["e", "a"], ["b", "d"], ["f", "c"]]
let array = [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[2, 2, 2, 2, 2, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]
let shuffled = shuffle2D(array)
print(shuffled)
[[0, 1, 0, 1, 1, 0, 1, 1, 0, 0], [0, 1, 0, 0, 1, 1, 1, 2, 0, 1], [0, 1, 1, 1, 0, 1, 1, 1, 1, 1], [1, 0, 1, 0, 2, 1, 2, 1, 0, 1], [1, 0, 0, 0, 2, 1, 1, 0, 1, 1], [1, 1, 0, 0, 0, 0, 0, 1, 1, 1], [0, 0, 1, 1, 2, 0, 0, 1, 1, 0], [1, 0, 1, 1, 0, 0, 0, 1, 1, 0], [0, 0, 0, 1, 1, 0, 1, 1, 1, 0], [1, 1, 0, 0, 0, 0, 1, 0, 0, 0]]