Yes. There are a number of ways to do it. Probably the cleanest looking would be to use the reduce()
function:
const obj = { 1: 'a', 2: 'b', 3: 'c', 4: 'd', 5: 'e', 6: 'f', 7: 'g', 8: 'h', 9: 'i' };
const width = 3; // how many in each sub array.
const result = Object.keys(obj).map(key => obj[key]) // ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
.reduce((result, v) => {
if (result[result.length - 1].length === width) {
result.push([v]); // add new row
} else {
result[result.length - 1].push(v); // add to last row
}
return result;
}, [[]]);
console.log(result);
This is a little more verbose then it needs to be, but more understandable.
First, I loop through and map()
the object to a normal array.
Then, in the reduce()
function, I start it with the first level of nested arrays. Then on each loop, I check the length of the last array in result. If it's full, I add a new array for the next row. Otherwise, I just add the value to the last row.
A more compact version would be:
const obj = { 1: 'a', 2: 'b', 3: 'c', 4: 'd', 5: 'e', 6: 'f', 7: 'g', 8: 'h', 9: 'i' };
const width = 3;
const result = Object.keys(obj).reduce((r, k) =>
r.concat(
r[r.length - 1].length === width
? [[obj[k]]]
: [r.pop().concat(obj[k])]
), [[]]);
console.log(result);
This example makes more use of .concat()
so everything is technically on one line, though obviously it's a good bit harder to read and understand.