I have the array: [1,2,3,4,5,6,7]
I want to achieve: [[1,2], [3,4], [5,6], [7]]
I'm thinking Array.map, but it doesn't seem to be able to map to nothing for an element?
I have (using Underscorejs):
arr.map(function(el, idx, arr) {
if (idx%2 != 0) return null;
if (idx == arr.length-1) return [el];
return [el, arr[idx+1]]
})pact();
This is still a bit ugly. How can I achieve the transformation (without explicit loop)?
I have the array: [1,2,3,4,5,6,7]
I want to achieve: [[1,2], [3,4], [5,6], [7]]
I'm thinking Array.map, but it doesn't seem to be able to map to nothing for an element?
I have (using Underscorejs):
arr.map(function(el, idx, arr) {
if (idx%2 != 0) return null;
if (idx == arr.length-1) return [el];
return [el, arr[idx+1]]
}).compact();
This is still a bit ugly. How can I achieve the transformation (without explicit loop)?
Share Improve this question edited Mar 16, 2016 at 12:22 Boyang asked Mar 16, 2016 at 12:15 BoyangBoyang 2,5665 gold badges34 silver badges50 bronze badges 1 |6 Answers
Reset to default 6reduce
the array using the modulo operator:
function chunk(arr, n) {
return arr.reduce(function (p, c, i) {
if (i % n === 0) p.push([]);
p[p.length - 1].push(c);
return p;
}, []);
}
chunk(arr, 2); // [[1,2],[3,4],[5,6],[7]]
DEMO
The map
function can't do that, it's a structure-preserving transformation.
You could write this "chunking" as a reduce
, a plain loop, or something weird like
var arr = [1,2,3,4,5,6,7];
return arr.filter(function(_, i) {
return i%2==0;
}).map(function(x, i) {
return i*2+1<arr.length ? [x, arr[i*2+1]] : [x];
});
or
return arr.map(function(_, i) {
return arr.slice(i, 2);
}).filter(function(_, i) {
return i%2==0;
})
See also Split array into chunks for many more variants (some of them quite functional).
One more wired solution in one loop.
var array = [1, 2, 3, 4, 5, 6, 7],
result = array.reduce(function (r, a, i) {
i & 1 && r[i >> 1].push(a) || r.push([a]);
return r;
}, []);
document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');
Or functional (it utilized Fat_Freddy's idea)
function due(array) {
return array.length && [array.splice(0, 2)].concat(due(array)) || [];
}
var array = [1, 2, 3, 4, 5, 6, 7],
result = due(array.slice());
document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');
Try a combination of map and filter
var output = [1,2,3,4,5,6,7].map(function(value,index,arr){
if(index%2==0)
{
//return [value, arr[index+1]];
return index + 1 < arr.length ? [value, arr[index+1] ] : [ value ];
}
else
{
return false;
}
}).filter(function(value){return value});
console.log(output);
Can't you just do something like this?
EDITED to prevent original being altered, as per Andy's suggestion
var temp = original.slice();
var newList = [];
while(temp.length)
{
newList.push(temp.splice(0,2));
}
You can try array.slice()
and while loop for it.
Also using function like map
, filter
will iterate every element.
function splitArrayInLength(arr, len) {
var returnArr = [];
var index = 0;
while(index < arr.length){
returnArr.push(arr.slice(index, index + len));
index += len;
}
return returnArr;
}
function main() {
var arr = [1, 2, 3, 4, 5, 6, 7];
print(splitArrayInLength(arr, 2));
print(splitArrayInLength(arr, 4));
}
function print(obj){
document.write("<pre>" + JSON.stringify(obj, 0, 4) + "</pre><br/>");
}
main();
Array.map
will create a loop as well. Its just more cleaner approach. – Rajesh Commented Mar 16, 2016 at 12:17