0

I got this matrix that, depending on the results I receive from the server, the width can change. Basically, it can be something like

[undefined, undefined]
[1, 2, 3, 4]
[1, 2]
[undefined, undefined, undefined]
[1, 2, 3, 4, 5, 6]

and I want it to be like this

[undefined, 1, 1, undefined, 1]
[undefined, 2, 2, undefined, 2]
[undefined, 3,undefined, undefined, 3]
[undefined, 4, undefined, undefined, 4]
[undefined, undefined, undefined, undefined, 5]
[undefined, undefined, undefined, undefined, 6]

Notice that the height changed to the maximum width of the first example. I googled it and the best solution I got was this

array.map((row, i) => array.map(col => col[i]))

but this solution wont change my matrix height. I tried 2 for cycles but I think I didn't code it right as I was not getting the expected result. If someone could give me a little help, that would be awesome

4 Answers 4

4

There are a lot of ways to solve this (as other answers demonstrate). Here's how I'd do it, as it minimizes the number of times we iterate over the data.

const data = [
  [undefined, undefined],
  [1, 2, 3, 4],
  [1, 2],
  [undefined, undefined, undefined],
  [1, 2, 3, 4, 5, 6],
];

// get the length of the longest array
const maxLen = data.reduce((max, {length}) => Math.max(max, length), 0);

// make a new set of arrays
const result = Array.from({ length: maxLen }, (_, i) => data.map(col => col[i]));

console.log(result);

Sign up to request clarification or add additional context in comments.

1 Comment

I think it would be clearer if you called the map iterated element row instead of col data.map(row => row[i])
0

Assuming your matrix is stored in matrix,

const transformed = [];

const maxWidth = matrix.reduce((max, current) => {
    return (current.length > max) ? current.length : max;
}, 0);

// Loop over each column
for (let i = 0; i < maxWidth; i++) {
    const tRow = [];

    // Loop over each row of the current column
    for (const row of matrix) {
        tRow.push(row[i]);
    }

    transformed.push(tRow);
}

Comments

0

There are a few steps involved here.

  1. Find the max length.

  2. Normalise

  3. And then rotate

I've placed comments in code to show each part.

const input = [
  [undefined, undefined],
  [1, 2, 3, 4],
  [1, 2],
  [undefined, undefined, undefined],
  [1, 2, 3, 4, 5, 6]
];

//first find max length
const maxw = Math.max(...input.map(m => m.length));

//now normalize
const norm_inputs = input.map(m => 
  (new Array(maxw)).concat(m).slice(-maxw)
);

//now rotate..
const output = (new Array(maxw).fill(0)).map(
  (row, i) => norm_inputs.map(col => col[i]))

2 Comments

Your solution almost worked but even though the matrix had the height expected, it still only got the number of elements of the input matrix height.
@tiagomnf I had put -6 for the slice instead of -maxw, try now.
0

The more efficient solution:

const maxLength2d = (matrix) => {
  let result = 0

  for (const { length } of matrix) result = Math.max(result, length)

  return result
}

const transpose2d = (matrix, placeholder = undefined) => {
  const result = []
  const maxlen = maxLength2d(matrix)
  let y = 0

  for (const { length } = matrix; y < length; y++) {
    const inner = matrix[y]
    let x = 0

    for (const { length } = inner; x < length; x++) {
      result[x] ||= []
      result[x].push(inner[x])
    }

    for (; x < maxlen; x++) {
      result[x] ||= []
      result[x].push(placeholder)
    }
  }

  return result
}

const transposed = transpose2d(
  [
    [1, 2],
    ['a', 'b', 'c', 'd'],
  ]
)

console.log('transposed', transposed)

console.log('transposed back', transpose2d(transposed))

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.