6

I have this array:

rows = [ [ 89, 18, 9 ], [ 1903, 3, 4 ], [ 3, 1, 800 ] ];

It should look like this:

[ [ 89, 1903, 3 ], [ 18, 3, 1 ], [ 9, 4, 800 ] ]

And the code, that is working, looks like this:

rows[0].map((_, columnIndex) => rows.map(
            row => row[columnIndex])
        );

How does this work?

4
  • 1
    The description for the 2d tag is 2D computer graphics is the computer-based generation of digital images—mostly from two-dimensional models. - totally not what you're talking about Commented Mar 5, 2018 at 22:56
  • 1
    You're transposing your data structure, which only works with that code because it's square. Either way, perhaps you could explain which parts confuse you? Did you check up on what map does yet? Commented Mar 5, 2018 at 23:05
  • 1
    I understand what map does, but i don't understand how the second chained map gets to the right array elements. Can you explain me that? Commented Mar 5, 2018 at 23:12
  • @Jeroen Doesn't have to be square. It could be any rectangular array. It's just that the names of the variables are misleading. I'd rather write rows[0].map((_, columnIndex) => rows.map(row => row[columnIndex])). Commented Mar 5, 2018 at 23:46

4 Answers 4

8

I'll assume you are simply not accustomed to the particular language features being used here, hence why you can't follow what is going on, so here goes:

  • Your structure is a nested Array. Hence the nested Array.maps.

  • Both map callbacks make use of implicit return.

which unfolds to this:

rows[0].map((row, index) => {
  return rows.map((column) => {
    return column[index]
  })
})

The 2 arguments passed to the map callback are the following:

  • element: The currently iterated Array element; In your first map this is the row argument.
  • i: The current iteration number, starting from 0; In your first map this is the index argument.

That's all there is to it. From then on you just follow the iterations and the values of each argument at each iteration.

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

Comments

2
                  +--- The outter function map gets the first array to loop through the rows
[ 89,   18, 9   ] |
[ 1903, 3,  4   ] |
[ 3,    1,  800 ] v
  +--->
  |
  +- The nested function map is looping through the columns.
     The key here is the fixed column using index (column[index])
     from the outter function map, so every iteration from the outter
     function map will fix the access to that column, i.e -
     index = 0 will access the array as follow: array[j][0], array[j+1, 0], ... array[n, 0]
                                                         ^              ^                ^

This is an approach to illustrate what's happening using direct index accesses.

var rows = [ [ 89, 18, 9 ], [ 1903, 3, 4 ], [ 3, 1, 800 ] ];

var result = [];
for (var i = 0; i < rows[0].length; i++) {
  result[i] = new Array(rows[0].length).fill();

  for (var j = 0; j < rows.length; j++) {
    result[i][j] = rows[j][i]; // Here is the fixed column access using the outter index i.
  }
}

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

2 Comments

Was just writing my own near identical answer. +1. My for loop was slightly different to yours though: for(var i = 0; i < rows[0].length; i++){ result.push([]); for(var j = 0; j < rows.length; j++){ result[result.length-1].push(rows[j][i]); } }
@Zze yes, it was similar!
0

Iterator Methods (like map,forEach,filter...) dealing with array 2d as every element is 1d array

For example:

    arr= [[1,0,0],
          [0,1,0],
          [0,0,1]]
    arr.map( (item)=> {
           item.forEach( (element)=> {
             //...
            //...
           })
    })

The first iterator (map) take the first row in arr array in this example [1,0,0]

The second iterator takes the second row of arr that is [0,1,0] save it in item and so on...

In a nested loop (foreach) that take the real number like 0 or 1. Here the code can deal with it.

1 Comment

This answer is a bit unclear for me. Save it in item? Here the code can deal with it? What does this mean?
0

Wrapping one's head around multi-dimensional arrays is confusing enough by itself (compare the comments above about square vs. non-square), but there's a bit more going on here than was previously explained.

Consider the inner part: rows.map( row => row[columnIndex] ). This is straightforward: for each row we extract the value in the specified column position, so this makes a 1-dimensional array representing a column in the original array ("rows") - e.g. if columnindex is 2 this returns [9, 4, 800]. Note that "rows" is being referenced here as a variable external to the map function, whereas "row" is just an internal name of the map function referring to the array element being processed, and the argument "columnIndex" is being passed in from the outer map() call.

Now the outer map function is being applied to the elements of rows[0] (and NOT to rows itself!), meaning it takes that first row (simply to determine how many columns there are!) and walks through it, disregarding the current value completely (that's why the generic underscore is used) and only caring about the current position in that array, i.e. the columnIndex. For each column index it will return the output of that inner map we just discussed.

To be clear, this works just fine on any rectangular array: if your original array had had 3 rows of 4 values each, the outer map would have walked through those 4 positions, and for each of them returned an array of 3 values extracted from the 3 rows at that given position, so the resulting array would have had 4 rows of 3 values each, perfectly transposing the original matrix.

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.