2016-10-06 4 views
1

Я задал подобный вопрос некоторое время назад. Она спрашивает, как я могу превратить массив так:Как сгладить массив * таким образом * быстро?

[[1,2,3],[4,5,6],[7,8,9]] 

к этому:

[1,2,3,4,5,6,7,8,9] 

Но теперь я хочу, чтобы превратить тот же массив следующим образом:

[1,4,7,2,5,8,3,6,9] 

Пусть все субмарины имеют одинаковую длину.

Если вы еще не заметили, первые три элемента в результате - это первый элемент из трех подмассивов. Четвертый, пятый и шестой позиции в результате - второй элемент каждого подмассива.

Если вы до сих пор не понимаю, может быть, это поможет:

Оригинальный массив:

Результат:

[ 
    1,4,7, 
    2,5,8, 
    3,6,9 
] 

На данный момент у меня есть это:

func flatten(array: [[Int]]) -> [Int] { 
    var flat = [Int]() 
    for i in 0..<array[0].count { 
     for subarray in array { 
      flat.append(subarray[i]) 
     } 
    } 
    return flat 
} 

Я не думаю, что это очень swfity. Как я могу сделать это осторожно?

Чтобы избежать проблем с XY, вот почему я хочу это сделать.

Я разрабатываю настольную игру. Я использую HLGridNode (Это в основном куча квадратов в виде сетки) от HLSpriteKit доски настольной игры. Чтобы отредактировать содержимое узла сетки, мне нужно передать в 1D массив узлов спрайтов, а не 2D-массив.

Чтобы облегчить мою жизнь, я сохранил объекты модели в 2D-массиве. Таким образом, я могу сослаться на Sqaure 5 квадратов слева и 2 квадрата с вершины просто делать:

modelObjects[5][2] 

Если я придавить 2D массив, используя .flatMap { $0 } и передать результат в узел сетки, modelObjects[5][2] бы кажутся 2 квадратами слева и 5 квадратами сверху.

Это не дубликат this, потому что у этого вопроса есть определенное количество массивов для работы. Хотя я могу поместить свой 2D-массив в цикл и сделать эти вещи enumerate().map {...}, это похоже на очень длинный подход. Я думаю, что должно быть проще сделать это с помощью 2D-массивов.

+4

Возможный дубликат [Объединение нескольких массивов в один, индексирование последовательно] (http://stackoverflow.com/questions/39696381/combining-multiple-arrays-into-one-indexing-sequential) – Hamish

+0

«Я разрабатываю настольную игру. " Это проблема, которую вы пытаетесь решить. Вы уже решили проблему с массивом. Больше времени, потраченное на это, является отвлечением от вашей реальной цели. Это не значит, что проблема не интересна. Это просто не важно решить. –

+1

Re your edit: от быстрого просмотра «дублирующего кандидата» мне кажется, что у него есть ответы, которые * не * предполагают определенное количество массивов для работы. –

ответ

2

Вот улучшение на answerShadow Of «s:

func transpose<T>(matrix: [[T]]) -> [[T]] { 
    guard !matrix.isEmpty else { return matrix } 
    return matrix[0].indices.map{ index in 
     matrix.map{ $0[index] } 
    } 
} 
+0

Больше swifty =) –

+1

Это не Swifty, пока он не находится в расширении;) – Alexander

+0

Когда я попытался написать расширение, я схожу. Пытается использовать «карту», ​​вызвав «ошибку сегментации» без видимых причин, пытается использовать «признаки», вызванные раздражающими «невыполнимыми индексами». Наконец, я получаю эту рабочую версию. Я знаю, как записать его в swift 2, но вот в быстрых 3 он выглядит настолько уродливым. Можете ли вы посмотреть мой обновленный ответ и, возможно, указать на некоторые ошибки или сделать это более простым? –

1

Вы можете получить результат, который вы разыскиваетесь транспонировать вашу 2d матрицы, используя, например, эту функцию:

func matrixTranspose<T>(_ matrix: [[T]]) -> [[T]] { 
    if matrix.isEmpty {return matrix} 
    var result = [[T]]() 
    for index in 0..<matrix.first!.count { 
     result.append(matrix.map{$0[index]}) 
    } 
    return result 
} 

и применение flatten (joined в быстрых 3) затем.

let arr = [[1,2,3],[4,5,6],[7,8,9]] 
print(matrixTranspose(arr)) 
// [[1, 4, 7], [2, 5, 8], [3, 6, 9]] 

print(matrixTranspose(arr).flatMap{$0}) 
// [1, 4, 7, 2, 5, 8, 3, 6, 9] 

версия Расширение:

extension Collection where Self.Iterator.Element: Collection { 
    var transpose: Array<Array<Self.Iterator.Element.Iterator.Element>> { 
     var result = Array<Array<Self.Iterator.Element.Iterator.Element>>() 
     if self.isEmpty {return result} 

     var index = self.first!.startIndex 
     while index != self.first!.endIndex { 
      var subresult = Array<Self.Iterator.Element.Iterator.Element>() 
      for subarray in self { 
       subresult.append(subarray[index]) 
      } 
      result.append(subresult) 
      index = self.first!.index(after: index) 
     } 
     return result 
    } 
} 

с использованием

let arr = [[1,2,3],[4,5,6],[7,8,9]] 
print(arr.transpose) 
// [[1, 4, 7], [2, 5, 8], [3, 6, 9]] 
+0

Старайтесь избегать '0 .. Alexander

+2

Если вы создаете расширение для 'Array', вы должны просто добавить ограничение' Element.Indices.Iterator.Element == Element.Index' (см. [Этот вопрос и вопрос] (http://stackoverflow.com/questions/39179660/swift-2d-array-generic-extension-issue-accessing-2nd-dimension)) и просто используйте реализацию @ AlexanderMomchliov для расширения (замените 'matrix' на' self'). – Hamish