Search code examples
arraysswiftpad

Pad an array with 0's swift


I am attempting to pad an an array with zeros but cannot find a succinct way to do this in swift. If I have array x = [1,2,3 ; 4,5,6 ; 7,8,9] in matlab I could use the command

y = [zeros(1,3+2);zeros(3,1),x,zeros(3,1);zeros(1,3+2)]

giving the desired output array of [0,0,0,0,0; 0,1,2,3,0 ; 0,4,5,6,0 ; 0,7,8,9,0 ; 0,0,0,0,0]

However so far in a swift playground I have only been able to refer to each element individually to correctly form the new array.

The methods I have tried so far using x as the input and y as the output, the first similar to matlab,

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

var y = [[0,0,0,0,0],[0,x[0],0],[0,x[1],0],[0,x[2],0],[0,0,0,0,0]]

The second being a loop

for i in 0 ..< x.count + 1 {
  if i == 0 || i == x.count - 1 {
    y[i] = [0,0,0,0,0]
  }
  else{
    y[i] = [0, x[i-1] ,0]
  }
}

Rather than looking like a standard array in the Xcode playground preview this is the output given.

[[0, 0, 0, 0, 0], [0, […], 0], [0, 0, 0, 0, 0], [0, […], 0], [0, 0, 0, 0, 0]]

which also prints to the console very strangely, using the code

for i in 0 ..< y.count {
    print("\(y[i])")
}

the output is

(
    0,
    0,
    0,
    0,
    0
)
(
    0,
        (
        1,
        2,
        3
    ),
    0
)
(
    0,
    0,
    0,
    0,
    0
)
(
    0,
        (
        7,
        8,
        9
    ),
    0
)
(
    0,
    0,
    0,
    0,
    0
)

as opposed to the expected

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

What is the best way to do this?


Solution

  • I made a generic version of appzYourLife's answer that can take any arbitrary nested array type. It also adds support for top and bottom padding

    extension Array where Element: _ArrayType {
        typealias InnerElement = Element.Generator.Element
    
        func pad2DArray(with padding: InnerElement,
                        top: Int = 0, left: Int = 0,
                        right: Int = 0, bottom: Int = 0) -> [[InnerElement]] {
            let newHeight = self.count + top + bottom
            let newWidth = (self.first?.count ?? 0) + left + right
    
            var paddedArray = [[InnerElement]](count: newHeight, repeatedValue:
                            [InnerElement](count: newWidth, repeatedValue: padding))
    
            for (rowIndex, row) in self.enumerate() {
                for (columnIndex, element) in row.enumerate() {
                    paddedArray[rowIndex + top][columnIndex + left] = element
                }
            }
    
            return paddedArray
        }
    }
    
    var input = [
        [1, 2, 3],
        [4, 5, 6],
        [7, 8, 9]
    ]
    
    let result = input.pad2DArray(with: 0, top: 1, left: 1, right: 1, bottom: 1)
    
    /*
    result:
    [
        [0, 0, 0, 0, 0],
        [0, 1, 2, 3, 0],
        [0, 4, 5, 6, 0],
        [0, 7, 8, 9, 0],
        [0, 0, 0, 0, 0],
    ]
    */