0

I have to do some operations with matrices (nested arrays) and I've encountered a 'funny' situation that I'm not sure why it's happening. I have these two functions:

function createNDMatrix(
    dimensions_lengths: number[],
    fill_value: number | null = null
): any {
    if (dimensions_lengths.length === 1) {
        return Array(dimensions_lengths[0]).fill(fill_value);
    } else {
        return Array(dimensions_lengths[dimensions_lengths.length - 1]).fill(
            createNDMatrix(dimensions_lengths.slice(0, dimensions_lengths.length - 1), fill_value)
        );
    }
}
function nestedFill(
    array_to_fill: any,
    position_to_fill: number[],
    fill_value: number | null
): void {
    if (position_to_fill.length === 1) {
        array_to_fill[position_to_fill[0]] = fill_value;
    } else {
        nestedFill(
            array_to_fill[position_to_fill[position_to_fill.length - 1]],
            position_to_fill.slice(0, position_to_fill.length - 1),
            fill_value
        );
    }
}

createNDMatrix allows me to create an arbitrary nested matrix such that createNDMatrix([2, 2, 2], null) => [[[null, null],[null, null]],[[null, null],[null, null]]] and nestedFill allows me to fill an arbitrary nested (provided) matrix such that nestedFill([[[null, null],[null, null]],[[null, null],[null, null]]], [0, 1, 1], 10) => [[[null, null],[null, null]],[[null, null],[10, null]]]

Up to here everything behaves as I expected; both functions are recursive, but the way the nestedFill function fills the matrix, and the way that createNDMatrix creates the matrix makes me think that the dimensions inside of them shouldn't be pointing at each other. However, when I do nestedFill(createNDMatrix([2, 2, 2], null), 10) I get as a result [ [ [ 10, null ], [ 10, null ] ], [ [ 10, null ], [ 10, null ] ] ], which I don't understand why it happens.

Obviously there is something wrong with the createNDMatrix function when filling in arrays recursively, but I can't understand why. Does anybody know why this happens? Here is a working demonstration of my problem

P.Gracia
  • 214
  • 1
  • 2
  • 9
  • 1
    Don't pass non-primitives to `.fill`, use `Array.from` instead – CertainPerformance Apr 11 '20 at 10:10
  • 1
    @P.Gracia If you do this -> `var x = Array(10).fill([1,2,3])`, your array will basically be filled with 10 identical array's, arrays that are using the same memory location. Arrays in JS are Object's, so are copied by reference. IOW: `x[0], x[1],..` all point to the same array. A simple solution to this is just fill the array with anything, and then map. eg. `var x = Array(10).fill(undefined).map(f => [1,2,3])`, Here is an updated sandbox doing that -> https://codesandbox.io/s/bitter-surf-1tj90?file=/src/index.ts – Keith Apr 11 '20 at 15:58

0 Answers0