Unpredictable behaviour while changing iteration direction in a 2D array and element sort

Viewed 45

Let's say that I have a 2D array:

┌─────────┬───┬───┬───┐
│ (index) │ 0 │ 1 │ 2 │
├─────────┼───┼───┼───┤
│    0    │ 2 │ 3 │ 2 │
│    1    │ 3 │ 1 │ 3 │
│    2    │ 2 │ 2 │ 3 │
└─────────┴───┴───┴───┘

I want to sort elements in the 2D array and put them in line with direction from the top to the bottom like below:

┌─────────┬───┬───┬───┐
│ (index) │ 0 │ 1 │ 2 │
├─────────┼───┼───┼───┤
│    0    │ 1 │ 2 │ 3 │
│    1    │ 2 │ 2 │ 3 │
│    2    │ 2 │ 3 │ 3 │
└─────────┴───┴───┴───┘

So far I have a code like:

const generateArray = (size, min, max) =>
    Array(size)
    .fill(0)
    .map(() => generateNumber(min, max));

const generateArray2D = (rows, cols, min, max) =>
    Array(rows)
    .fill(0)
    .map(() => generateArray(cols, min, max));

const generateNumber = (min, max) =>
    Math.floor(Math.random() * (max - min + 1)) + Math.floor(min);

const generated2DArray = generateArray2D(
    rows,
    cols,
    10,
    30
);

const sortedArray = [...generated2DArray].flat(1).sort(((a, b) => a - b))

for (const sortedElement of sortedArray) {
  for (let j = 0; j < generated2DArray.length; j++) {
    for (let i = 0; i < generated2DArray[j].length; i++) {
      generated2DArray[i][j] = sortedElement;
    }
  }
}

But every field of result array contains the last element from the sorted sortedArray like below:

┌─────────┬────┬────┬────┬────┬────┐
│ (index) │ 0  │ 1  │ 2  │ 3  │ 4  │
├─────────┼────┼────┼────┼────┼────┤
│    0    │ 30 │ 30 │ 30 │ 30 │ 30 │
│    1    │ 30 │ 30 │ 30 │ 30 │ 30 │
│    2    │ 30 │ 30 │ 30 │ 30 │ 30 │
│    3    │ 30 │ 30 │ 30 │ 30 │ 30 │
│    4    │ 30 │ 30 │ 30 │ 30 │ 30 │
└─────────┴────┴────┴────┴────┴────┘

I tried a couple of options but, I don't see the potential cause of the problem. Thank you in advance for suggestions on how to fix the above problem.

3 Answers

The first time through the outer loop, the two inner loops set all the elements of the result array to sortedArray[0]. The second time it sets all of them to sortedArray[1], and so on. Each time through the outer loop you set the entire generated2DArray to the same value.

Don't use the outer loop, just loop through the indexes in the 2D array, and increment the index in the 1D array without another loop.

  k = 0;
  for (let j = 0; j < generated2DArray.length; j++) {
    for (let i = 0; i < generated2DArray[j].length; i++) {
      generated2DArray[i][j] = sortedArray[k++];
    }
  }

The problem is, you are looping over the entire grid for every item in your sorted flat array.

Try removing the outer loop and determining the position in the 2d array like this:

for (let j = 0; j < generated2DArray.length; j++) {
    for (let i = 0; i < generated2DArray[j].length; i++) {
        generated2DArray[i][j] = sortedArray[i*generated2DArray.length+j];
    }
}

You could just calculate the index of current row and col based on the index of current element in the sorted array and based on those two values change the value of the output array.

const generateArray = (size, min, max) =>
  Array(size)
  .fill(0)
  .map(() => generateNumber(min, max));

const generateArray2D = (rows, cols, min, max) =>
  Array(rows)
  .fill(0)
  .map(() => generateArray(cols, min, max));

const generateNumber = (min, max) =>
  Math.floor(Math.random() * (max - min + 1)) + Math.floor(min);

const rows = 3
const cols = 4

const generated2DArray = generateArray2D(rows, cols, 10, 30);
const sortedArray = [...generated2DArray].flat(1).sort(((a, b) => a - b))

for (let i in sortedArray) {
  const col = Math.floor(i / rows)
  const row = i - (col * rows)

  generated2DArray[row][col] = sortedArray[i]
}

for (let a of generated2DArray) {
  console.log(JSON.stringify(a))
}

Related