2

If I have a one-dimensional array:

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

and I already have a 3X3 two-dimensional array with the right amount of slots to fit the numbers

twoDimArray = [[0,0,0], [0,0,0], [0,0,0]]

...how do I fit the oneDimArray numbers into the twoDimArray, like:

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

?

I know I can do this with a couple of nested for-loops, but is there a simpler, functional way to do this?

cannyboy
  • 24,180
  • 40
  • 146
  • 252
  • (not familiar with Swift) you should be able to do a `reduce` operation or even a recursive algorithm. Not sure what the best tool Swift has for these. If you know the exact number of slots and they follow a pattern, you can derive locations mathematically and do it in a straight loop: `threeDimArray[i / 3][i % 3] = oneDimArray[i]` (where `/` performs integer division). – VLAZ Jan 20 '20 at 13:10
  • 1
    Why do you call a 2-dimensional array `threeDimArray`? – Martin R Jan 20 '20 at 13:15
  • good point @MartinR - updated – cannyboy Jan 20 '20 at 13:16

4 Answers4

9

Here is one way to do it. Make an iterator out of your one dimensional array, and then use map and compactMap along with .next() to replace the values of the twoDimArray to create the newArray:

let oneDimArray = [1,2,3,4,5,6,7,8,9]
let twoDimArray = [[0,0,0], [0,0,0], [0,0,0]]

var iter = oneDimArray.makeIterator()
let newArray = twoDimArray.map { $0.compactMap { _ in iter.next() } }
print(newArray)

Output

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

A nice feature of this technique is that you can easily fill in any pattern of array, and not just create a fixed 3x3 one for instance:

let oneDimArray = [1,2,3,4,5,6,7,8,9,10]
let patternArray = [[0], [0,0], [0,0,0], [0,0,0,0]]

var iter = oneDimArray.makeIterator()
let newArray = patternArray.map { $0.compactMap { _ in iter.next() } }
print(newArray)

Output

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

A generic function

We can turn this into a generic function that can replace the values of a 2D array with those of a 1D array. Note that the types of the values in the arrays can be different if you like:

func overlay<T, U>(_ array: [[T]], values: [U]) -> [[U]] {
    var iter = values.makeIterator()
    return array.map { $0.compactMap { _ in iter.next() }}
}

// Create an 2D array of strings from this pattern   
let patternArray = [[0], [0,0], [0,0,0], [0,0,0,0]]

print(overlay(patternArray, values: ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"]))

Output

[["a"], ["b", "c"], ["d", "e", "f"], ["g", "h", "i", "j"]]
vacawama
  • 150,663
  • 30
  • 266
  • 294
4

You can loop over index and value using enumerated and then calculate the correct postion using % and /

for (index, num) in oneDimArray.enumerated() {
    twoDimArray[index / 3][index % 3] = num
}
cannyboy
  • 24,180
  • 40
  • 146
  • 252
Joakim Danielson
  • 43,251
  • 5
  • 22
  • 52
2
var index = 0
twoDimArray.indices.forEach { (outerInd) in
    twoDimArray[outerInd].indices.forEach { (innerInd) in
        twoDimArray[outerInd][innerInd] = oneDimArray[index]
        index += 1
    }
}
cannyboy
  • 24,180
  • 40
  • 146
  • 252
Li Mengran
  • 367
  • 1
  • 5
0
for i in twoDimArray.indices {
    for j in twoDimArray[i].indices {
        twoDimArray[i][j] = oneDimArray.removeFirst();
    }
}
Emil Laine
  • 41,598
  • 9
  • 101
  • 157
  • See "[Explaining entirely code-based answers](https://meta.stackoverflow.com/q/392712/128421)". While this might be technically correct it doesn't explain why it solves the problem or should be the selected answer. We should educate in addition to help solve the problem. – the Tin Man Jan 20 '20 at 21:57