Как перемешать многомерный массив? - PullRequest
2 голосов
/ 25 июня 2019

Я пытаюсь случайным образом перемешать 2D-массив. как мне это сделать? Я знаю только способ перемешать один массив с методом перемешивания. Должен ли я объединить весь 2d массив в один большой массив и перемешать и сделать его 2d массивом или есть лучший подход?

[[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]]

Ответы [ 4 ]

2 голосов
/ 25 июня 2019

Вы правы, что хороший способ приблизиться к перемешиванию двумерного массива - это сгладить его и перемешать значения.Сложность в том, как вернуть перемешанные значения обратно в исходную структуру массива.

Превратив перемешанный массив в итератор iter, мы можем вызвать iter.next(), чтобы получить каждое значение и использовать вложенныеmap s для доступа к исходным значениям и их замены:

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]]
1 голос
/ 25 июня 2019

Вы можете перебирать внешний массив с помощью цикла for и перемешивать каждый массив, через который вы перебираете, с помощью метода shuffle. Вот моя идея в псевдокоде:

for inner_array in outer_array:
    shuffle(inner_array)

Редактировать

Насколько я понимаю ваш вопрос сейчас, я бы попытался добавить существующий массив в новый массив в не очень случайном порядке, например:

new_array = []
for i=0; i < oldarray.length(); i++:
    new_array.append(oldarray[randomNumber])

Вам придется искать возможные дубликаты (то есть, удаляя массив в цикле for из старого массива) и причины, по которой ваш randomNumber генерируется между границами oldarray.

Вы можете использовать первый ответ и второй ответ вместе фактически в зависимости от ваших потребностей.

1 голос
/ 25 июня 2019

Прежде всего получите один комбинированный перетасованный массив из многомерного массива, например:

let arr = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]
let shuffled = arr.joined().shuffled() //[1, 2, 5, 6, 11, 9, 4, 7, 12, 3, 8, 10]

Создайте расширение, которое разделяет один массив на куски, т.е.

extension Array {
    func chunks(of size: Int) -> [[Element]] {
        return stride(from: 0, to: self.count, by: size).map {
            Array(self[$0 ..< Swift.min($0 + size, count)])
        }
    }
}

Использование:

let result = shuffled.chunks(of: 3) [[3, 1, 2], [5, 6, 4], [7, 8, 9], [11, 10, 12]]
0 голосов
/ 25 июня 2019

Вы всегда можете сделать это так:

var matrix = [[1, 3, 2], [7, 1, 2], [9, 4, 1]]
var shuffled = matrix.map({ $0.shuffled() })

print(shuffled)

Один из возможных выходов:

[[3, 2, 1], [2, 7, 1], [9, 4, 1]]

Редактировать:

Если вся матрица должна быть перетасована, вам, вероятно, следует сначала спроецировать матрицу, перетасовать массив, а затем разбить массив обратно на матрицу.

Если вы беспокоитесь о производительности, вам следует выполнить некоторые действия.хорошо известный алгоритм перестановки массивов ( Knuth shuffle ), но с неповрежденной матрицей.Вместо этого используйте вариант линеаризованной матрицы (где вы преобразуете позицию матрицы (x, y) в векторную позицию (y * (x - 1)) + y)

...