normal array to multi-dimensional array

I know there's already answer for a similar question, but the outcome is not what I'm looking for.

I want to have [0,1,2,3,4,5,6,7,8] inserted into a multi-dimensional array like:

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

instead of:

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

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

Other than using for...loop, is there a shorter way to do it?

5 answers

  • answered 2018-11-08 07:11 Nitish Narang

    You can try this. I have used "Array.reduce" with "Object.values" to achieve this.

    var arr = [0,1,2,3,4,5,6,7,8]
    
    var toMatrix = (arr, width) => {
    
      let gap = Math.ceil(arr.length/width)
      
      return Object.values(arr.reduce((o,d,i) => (o[i%gap] = (o[i%gap] || []).concat(d), o), {}))
    }
    
    console.log(toMatrix(arr, 3))
    
    console.log(toMatrix(arr, 2))

  • answered 2018-11-08 07:53 Nina Scholz

    You could take a remainder with ttha actual index and push the value to the result set.

    const
        toMatrix = (array, width) => array.reduce((r, v, i) => {
            (r[i % width] = r[i % width] || []).push(v);
            return r;
        }, []),
        format = array => array.map(a => a.join(' '));
    
    console.log(format(toMatrix([0, 1, 2, 3, 4, 5, 6, 7, 8], 2)));
    console.log(format(toMatrix([0, 1, 2, 3, 4, 5, 6, 7, 8], 3)));
    console.log(format(toMatrix([0, 1, 2, 3, 4, 5, 6, 7, 8], 4)));
    .as-console-wrapper { max-height: 100% !important; top: 0; }

  • answered 2018-11-08 07:54 Mohammed Ashfaq

    input =[0,1,2,3,4,5,6,7,8]
    
    function divideInGroups (array, groupCount) {
     return input.reduce((acc, curr, index)=> {
       let group = index % groupCount;
       if(!acc[group]) acc[group]=[];
       acc[group].push(curr);
       return acc
     },[])
    }
    
    console.log("3 Groups", divideInGroups(input,3));
    console.log("2 Groups", divideInGroups(input,2));
    console.log("1 Groups",divideInGroups(input,1));
    console.log("5 Groups",divideInGroups(input,5));

  • answered 2018-11-08 09:21 vibhor1997a

    Although there are many solutions already posted for this but anyway I'm going to post mine as I think its readable, viable and according to the OP's use case.

    const toMatrix = (arr, width) => arr.reduce((rows, key, index) => {
        let chunkLength = Math.ceil(arr.length / width);
        let rowIndex = Math.ceil(index % chunkLength);
        rows[rowIndex] ? rows[rowIndex].push(key) : rows.push([key]);
        return rows;
    }, []);
    

    const arr = [0, 1, 2, 3, 4, 5, 6, 7, 8]
    const toMatrix = (arr, width) => arr.reduce((rows, key, index) => {
        let chunkLength = Math.ceil(arr.length / width);
        let rowIndex = Math.ceil(index % chunkLength);
        rows[rowIndex] ? rows[rowIndex].push(key) : rows.push([key]);
        return rows;
    }, []);
    
    console.log(toMatrix(arr, 3));
    console.log(toMatrix(arr, 2));
    console.log(toMatrix(arr, 1));
    console.log(toMatrix(arr, 4));
    console.log(toMatrix(arr, 5));

  • answered 2018-11-08 09:43 hygull

    If you wish, you can also try the below code.

    function splitToArrays(arr, width=1) {
    	/**
    	 * PARAMETERS:-
    	 * 	   arr   : array of numbers (integers in this case)
    	 * 	   width : number of elements in each sub array
    	 */
    
    	let newArr = [];
    	let times  = arr.length / width; 
    
    	for(let i = 0; i < width; i++) // each iteration adds a new sub array to newArr
    	{
    		let step = 0;
    		for(let j = 0; j < times; j = j + 1) { // each iteration adds new element to sub array
    			
    			if(j === 0) {
    				let item = arr[i + step]; // fetch item from array
    				newArr.push([item]);      // push item to new array
    				step += width;
    				continue; // continue with next iteration, 
    				          // skip the following statements
    			}
    
    			// else
    			let item = arr[i + step]; // 0, 3, 6 | 1, 4, 7
    			newArr[i].push(item);
    			step += width; // increment step's value by 3 in this case
    		}
    	}
    
    	// finally
    	return newArr;
    }
    
    
    function main() {
    	// test case
    	let a = [0, 1, 2, 3, 4, 5, 6, 7, 8];
    	let b = splitToArrays(a, 3); // 3 denotes number of elements inside sub arrays
    
    	console.log(a);
    	console.log(b);
    }
    
    main();
    
    /*
    	[ 0, 1, 2, 3, 4, 5, 6, 7, 8 ]
    	[ [ 0, 3, 6 ], [ 1, 4, 7 ], [ 2, 5, 8 ] ]
    */