Bakhtiyor
Bakhtiyor

Reputation: 7318

Convert simple array into two-dimensional array (matrix)

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.

Upvotes: 50

Views: 78646

Answers (21)

RecuencoJones
RecuencoJones

Reputation: 2867

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));
}

Upvotes: 0

Nimit Jain
Nimit Jain

Reputation: 11

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)

Upvotes: 0

Ver Greeneyes
Ver Greeneyes

Reputation: 36

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().

Upvotes: 1

Daomtthuan
Daomtthuan

Reputation: 19

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);

Upvotes: 1

MD Ashik
MD Ashik

Reputation: 9835

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))

Upvotes: 0

Ron Erlih
Ron Erlih

Reputation: 171

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..

Upvotes: 0

p8ul
p8ul

Reputation: 2320

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 ] ]

Upvotes: 3

Mustafa Dwaikat
Mustafa Dwaikat

Reputation: 3692

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

Upvotes: -1

cooogeee
cooogeee

Reputation: 189

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));

Upvotes: 2

Calle Bergstr&#246;m
Calle Bergstr&#246;m

Reputation: 488

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']
]

Upvotes: 6

Jayesh Vachhani
Jayesh Vachhani

Reputation: 101

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));

Upvotes: 0

jwueller
jwueller

Reputation: 30996

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]]

Upvotes: 70

Bhanu Prakash H c
Bhanu Prakash H c

Reputation: 173

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.

Upvotes: 15

samanime
samanime

Reputation: 26567

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;
  }, []);
}

Upvotes: 45

SayedRakib
SayedRakib

Reputation: 181

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);

Upvotes: 1

Jannic Beck
Jannic Beck

Reputation: 2425

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);

Upvotes: 1

Abdennour TOUMI
Abdennour TOUMI

Reputation: 93253

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)

Upvotes: -2

Sagar Mishra
Sagar Mishra

Reputation: 11

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);

Upvotes: 1

Andrew Whitaker
Andrew Whitaker

Reputation: 126052

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/

Upvotes: 4

cwallenpoole
cwallenpoole

Reputation: 82028

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));

Upvotes: 2

Vincent Mimoun-Prat
Vincent Mimoun-Prat

Reputation: 28541

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;
}

Upvotes: 2

Related Questions