50

Imagine I have an array:

A = Array(1, 2, 3, 4, 5, 6, 7, 8, 9);

And I want it to convert into 2-dimensional array (matrix of N x M), for instance like this:

A = Array(Array(1, 2, 3), Array(4, 5, 6), Array(7, 8, 9));

Note, that rows and columns of the matrix is changeable.

Mr. Polywhirl
49.2k12 gold badges96 silver badges147 bronze badges
asked Dec 20, 2010 at 17:55
4
  • 2
    Array.prototype.toMatrix=function(per){return this.reduce(function(prev,current,i){if(i%per==0)prev.push([current]);else prev[prev.length-1].push(current);return prev;},[])} Commented Dec 9, 2015 at 21:36
  • 1
    const chunk = (xs, n) => xs.length < n ? [xs] : [xs .slice (0, n), ... chunk (xs .slice (n), n)] Commented Mar 18, 2020 at 21:13
  • See duplicate: "Convert a 1D array to 2D array" for more responses. Commented Apr 27, 2021 at 15:56
  • [1,2,3,4,5,6,7,8,9].reduce((r,e,i)=>(i%3?r[r.length-1].push(e):r.push([e]))&&r,[]) Commented Feb 8, 2024 at 15:01

21 Answers 21

71

Something like this?

function listToMatrix(list, elementsPerSubArray) {
 var matrix = [], i, k;
 for (i = 0, k = -1; i < list.length; i++) {
 if (i % elementsPerSubArray === 0) {
 k++;
 matrix[k] = [];
 }
 matrix[k].push(list[i]);
 }
 return matrix;
}

Usage:

var matrix = listToMatrix([1, 2, 3, 4, 4, 5, 6, 7, 8, 9], 3);
// result: [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
answered Dec 20, 2010 at 18:00
Sign up to request clarification or add additional context in comments.

Comments

45

You can use the Array.prototype.reduce function to do this in one line.

ECMAScript 6 style:

myArr.reduce((rows, key, index) => (index % 3 == 0 ? rows.push([key]) 
 : rows[rows.length-1].push(key)) && rows, []);

"Normal" JavaScript:

myArr.reduce(function (rows, key, index) { 
 return (index % 3 == 0 ? rows.push([key]) 
 : rows[rows.length-1].push(key)) && rows;
}, []);

You can change the 3 to whatever you want the number of columns to be, or better yet, put it in a reusable function:

ECMAScript 6 style:

const toMatrix = (arr, width) => 
 arr.reduce((rows, key, index) => (index % width == 0 ? rows.push([key]) 
 : rows[rows.length-1].push(key)) && rows, []);

"Normal" JavaScript:

function toMatrix(arr, width) {
 return arr.reduce(function (rows, key, index) { 
 return (index % width == 0 ? rows.push([key]) 
 : rows[rows.length-1].push(key)) && rows;
 }, []);
}
answered Oct 3, 2016 at 19:21

2 Comments

Isn't it a good idea to avoid mutate the "rows" array? const toMatrix = (arr, width) => arr.reduce((rows, key, index) => (index % width === 0) ? [...rows, [key]] : [...rows.slice(0,-1), [...rows[rows.length -1], key]], []);
In the reduce() function, the first parameter of the callback is the value you will be returning. There is no harm in mutating it because it was made new just for this (initialized with the second parameter of reduce()). There is no need for the extra overhead of avoiding mutations on it (in fact, mutating is probably more performant). It still qualifies as "functional" programming.
15

This code is generic no need to worry about size and array, works universally

 function TwoDimensional(arr, size) 
 {
 var res = []; 
 for(var i=0;i < arr.length;i = i+size)
 res.push(arr.slice(i,i+size));
 return res;
 }
  1. Defining empty array.
  2. Iterate according to the size so we will get specified chunk.That's why I am incrementing i with size, because size can be 2,3,4,5,6......
  3. Here, first I am slicing from i to (i+size) and then I am pushing it to empty array res.
  4. Return the two-dimensional array.
Zippy
1,8365 gold badges28 silver badges37 bronze badges
answered Jul 6, 2017 at 10:41

Comments

6

The cleanest way I could come up with when stumbling across this myself was the following:

const arrayToMatrix = (array, columns) => Array(Math.ceil(array.length / columns)).fill('').reduce((acc, cur, index) => {
 return [...acc, [...array].splice(index * columns, columns)]
}, [])

where usage would be something like

const things = [
 'item 1', 'item 2',
 'item 1', 'item 2',
 'item 1', 'item 2'
]
const result = arrayToMatrix(things, 2)

where result ends up being

[
 ['item 1', 'item 2'],
 ['item 1', 'item 2'],
 ['item 1', 'item 2']
]
answered Jan 3, 2020 at 14:45

1 Comment

So cur is not used at all ?
4

How about something like:

var matrixify = function(arr, rows, cols) {
 var matrix = [];
 if (rows * cols === arr.length) {
 for(var i = 0; i < arr.length; i+= cols) {
 matrix.push(arr.slice(i, cols + i));
 }
 }
 return matrix;
};
var a = [0, 1, 2, 3, 4, 5, 6, 7];
matrixify(a, 2, 4);

http://jsfiddle.net/andrewwhitaker/ERAUs/

answered Dec 20, 2010 at 18:06

Comments

3

This a simple way to convert an array to a two-dimensional array.

function twoDarray(arr, totalPerArray) {
 let i = 0;
 let twoDimension = []; // Store the generated two D array
 let tempArr = [...arr]; // Avoid modifying original array
 while (i < arr.length) {
 let subArray = []; // Store 2D subArray
 for (var j = 0; j < totalPerArray; j++) {
 if (tempArr.length) subArray.push(tempArr.shift());
 }
 twoDimension[twoDimension.length] = subArray;
 i += totalPerArray;
 }
 return twoDimension;
}
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
twoDarray(arr, 3); // [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ] ]

answered Feb 5, 2020 at 15:17

3 Comments

Please do not code like this. It is very hard to see what's going on and the code is not reusable nor universal. I'd suggest taking a look at the other solutions presented here to see how they work.
Hi @RoyPrins. I have revised the answer to include a more reusable function. TY
Good show! You even caught the bit where you modified the original array.
2

Simply use two for loops:

var rowNum = 3;
var colNum = 3;
var k = 0;
var dest = new Array(rowNum);
for (i=0; i<rowNum; ++i) {
 var tmp = new Array(colNum);
 for (j=0; j<colNum; ++j) {
 tmp[j] = src[k];
 k++;
 }
 dest[i] = tmp;
}
answered Dec 20, 2010 at 18:02

1 Comment

Could you re-write it in C# please?
2
function matrixify( source, count )
{
 var matrixified = [];
 var tmp;
 // iterate through the source array
 for( var i = 0; i < source.length; i++ )
 {
 // use modulous to make sure you have the correct length.
 if( i % count == 0 )
 {
 // if tmp exists, push it to the return array
 if( tmp && tmp.length ) matrixified.push(tmp);
 // reset the temporary array
 tmp = [];
 }
 // add the current source value to the temp array.
 tmp.push(source[i])
 }
 // return the result
 return matrixified;
}

If you want to actually replace an array's internal values, I believe you can call the following:

source.splice(0, source.length, matrixify(source,3));
answered Dec 20, 2010 at 18:02

Comments

2

you can use push and slice like this

var array = [1,2,3,4,5,6,7,8,9] ;
var newarray = [[],[]] ;
newarray[0].push(array) ;
console.log(newarray[0]) ;

output will be

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

if you want divide array into 3 array

var array = [1,2,3,4,5,6,7,8,9] ;
var newarray = [[],[]] ;
newarray[0].push(array.slice(0,2)) ;
newarray[1].push(array.slice(3,5)) ;
newarray[2].push(array.slice(6,8)) ;

instead of three lines you can use splice

while(array.length) newarray.push(array.splice(0,3));
answered Jun 20, 2020 at 10:33

Comments

1
function changeDimension(arr, size) { 
 var arrLen = arr.length;
 var newArr = [];
 var count=0;
 var tempArr = [];
 for(var i=0; i<arrLen; i++) {
 count++;
 tempArr.push(arr[i]);
 if (count == size || i == arrLen-1) {
 newArr.push(tempArr);
 tempArr = [];
 count = 0;
 } 
 } 
 return newArr;
}
changeDimension([0, 1, 2, 3, 4, 5], 4);
answered Sep 11, 2015 at 12:36

1 Comment

Can you explain what is happening in the if (count == size || i == arrLen-1) {...} - what happens when i == arrLen-1?
1
function matrixify(array, n, m) {
 var result = [];
 for (var i = 0; i < n; i++) {
 result[i] = array.splice(0, m);
 }
 return result;
}
a = matrixify(a, 3, 3);
answered Jan 22, 2016 at 16:12

Comments

1
function chunkArrToMultiDimArr(arr, size) {
 var newArray = [];
 while(arr.length > 0)
 {
 newArray.push(arr.slice(0, size));
 arr = arr.slice(size);
 }
 return newArray;
}
//example - call function
chunkArrToMultiDimArr(["a", "b", "c", "d"], 2);
answered Oct 20, 2016 at 9:23

Comments

1
const x: any[] = ['abc', 'def', '532', '4ad', 'qwe', 'hf', 'fjgfj'];
// number of columns
const COL = 3;
const matrix = array.reduce((matrix, item, index) => {
 if (index % COL === 0) {
 matrix.push([]);
 }
 matrix[matrix.length - 1].push(item); 
 return matrix;
}, [])
console.log(matrix);
answered Oct 29, 2021 at 19:48

Comments

1

Using the Array grouping proposal (currently stage 3), you can now also do something like the following:

function chunkArray(array, perChunk) {
 return Object.values(array.group((_, i) => i / perChunk | 0));
}

See also the MDN documentation for Array.prototype.group().

answered Oct 5, 2022 at 11:54

Comments

1

Following up on @ver-greeneyes response with the latest Object.groupBy static function:

function chunkArray(array, perChunk) {
 return Object.values(Object.groupBy(array, (_, i) => i / perChunk | 0));
}
answered Oct 22, 2024 at 7:57

Comments

0

Simplest way with ES6 using Array.from()

const matrixify = (arr, size) => 
Array.from({ length: Math.ceil(arr.length / size) }, (v, i) => 
arr.slice(i * size, i * size + size));
const list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] ;
console.log(matrixify(list, 3));

answered Jan 9, 2019 at 8:16

Comments

0

Another stab at it,

  1. Creating an empty matrix (Array of row arrays)
  2. Iterating arr and assigning to matching rows

 function arrayToMatrix(arr, wantedRows) {
 // create a empty matrix (wantedRows Array of Arrays] 
 // with arr in scope
 return new Array(wantedRows).fill(arr)
 // replace with the next row from arr 
 .map(() => arr.splice(0, wantedRows))
 }
 // Initialize arr
 arr = new Array(16).fill(0).map((val, i) => i)
 // call!!
 console.log(arrayToMatrix(arr, 4));
 // Trying to make it nice
 const arrToMat = (arr, wantedRows) => new Array(wantedRows).fill(arr)
 .map(() => arr.splice(0, wantedRows))

(like in: this one)

(and: this one from other thread)

MatArray Class?

Extending an Array to add to a prototype, seems useful, it does need some features to complement the Array methods, maybe there is a case for a kind of MatArray Class? also for multidimensional mats and flattening them, maybe, maybe not..

answered Jul 15, 2021 at 16:03

Comments

0

1D Array convert 2D array via rows number:

function twoDimensional(array, row) {
 let newArray = [];
 let arraySize = Math.floor(array.length / row);
 let extraArraySize = array.length % row;
 while (array.length) {
 if (!!extraArraySize) {
 newArray.push(array.splice(0, arraySize + 1));
 extraArraySize--;
 } else {
 newArray.push(array.splice(0, arraySize));
 }
 }
 return newArray;
 }

 function twoDimensional(array, row) {
 let newArray = [];
 let arraySize = Math.floor(array.length / row);
 let extraArraySize = array.length % row;
 while (array.length) {
 if (!!extraArraySize) {
 newArray.push(array.splice(0, arraySize + 1));
 extraArraySize--;
 } else {
 newArray.push(array.splice(0, arraySize));
 }
 }
 return newArray;
 }
 
 console.log(twoDimensional([1,2,3,4,5,6,7,8,9,10,11,12,13,14], 3))

answered Sep 11, 2021 at 22:10

Comments

0

Now that the lodash library is quite relevant and used, here is a simple solution to get a chunked array :

const _ = require('lodash')
const chunkedArray = _.chunk(arrayToChunk, chunkSize)
answered Nov 7, 2023 at 9:34

Comments

-1

Short answer use:

const gridArray=(a,b)=>{const d=[];return a.forEach((e,f)=>{const 
h=Math.floor(f/b);d[h]=d[h]||[],d[h][f%b]=a[f]}),d};

Where:

a: is the array
b: is the number of columns
answered Jun 6, 2018 at 13:59

1 Comment

short but ugly.
-2

An awesome repository here .

  • api : masfufa.js

  • sample : masfufa.html

According to that sample , the following snippet resolve the issue :

 jsdk.getAPI('my');
 var A=[1, 2, 3, 4, 5, 6, 7, 8, 9];
 var MX=myAPI.getInstance('masfufa',{data:A,dim:'3x3'});

then :

MX.get[0][0] // -> 1 (first)
MX.get[2][2] // ->9 (last)
answered Nov 9, 2015 at 23:11

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.