How could I split an array by value like this:
[0, 1, 2, 0, 0, 0, 1, 0] =>
[[0, 1, 2], [0], [0], [0, 1], [0]]?
I'm using lodash documentary, but kinda out of ideas for now. Is there any way to do this with _.groupBy?
Thanks for your answers.
Use native JavaScrip Array#reduce method.
var data = [0, 1, 2, 0, 0, 0, 1, 0],
last;
var res = data.reduce(function(arr, v) {
// check the difference between last value and current
// value is 1
if (v - last == 1)
// if 1 then push the value into the last array element
arr[arr.length - 1].push(v)
else
// else push it as a new array element
arr.push([v]);
// update the last element value
last = v;
// return the array refernece
return arr;
// set initial value as empty array
}, [])
console.log(res);
If you have to start a new array when you encounter a zero you can resort to this code, hope it is not appear as vodoo programming.
var x = [0, 1, 2, 0, 0, 0, 1, 0];
x.join("") /* convert the array to a string */
.match(/(0[^0]*)/g) /* use a regex to split the string
into sequences starting with a zero
and running until you encounter
another zero */
.map(x=>x.split("")) /* get back the array splitting the
string chars one by one */
I assume that the array elements are just a digit long and that 0 is the start of every sub array.
Removing the one digit assumption would resort to this code:
var x = [0, 1, 2, 0, 12, 0, 0, 1, 0];
var the_regexp = /0(,[1-9]\d*)*/g;
x.join(",") /* convert the array to a comma separated
string */
.match(the_regexp) /* this regex is slightly different from
the previous one (see the note) */
.map(x=>x.split(",")) /* recreate the array */
In this solution we separate the array elements with a comma, Let's examine the regEx:
/0 means that every sub array starts with a 0, / is the beginning of the match
,[1-9]\d* this sub pattern match an the integer if it has a comma in front; the first digit cannot be 0, the other, optional, digits do not have this limitation. Thus we match ,1 or ,200 or ,9 or ,549302387439209.
We have to include in the subarray all the consecutive non zero number we find (,[1-9]\d*)* maybe none hence the second *.
`/g' closes the RegExp. The g indicates we want all the matches and not just the first one.
If you prefer an oneliner:
x.join(",").match(/0(,[1-9]\d*)*/g).map(x=>x.split(','));
or, if you prefer the pre ECMA2015 function expression syntax:
x.join(",").match(/0(,[1-9]\d*)*/g).map(function(x){return x.split(',');});
You could use a new array for every found zero value, otherwise append to the last array in the result set.
var array = [0, 1, 2, 0, 0, 0, 1, 0],
result = array.reduce(function (r, a) {
if (a) {
r[r.length - 1].push(a);
} else {
r.push([a]);
}
return r;
}, []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
[0, 1, 2, 0][0, 1, 2, 0, 0, 0, 1, 0, 2, 3, 4, 1, 2, 0, 0, 1]a valid input ?