# How to split an array into a number of arrays based on increasing value by a given number?

I’ve written the following function:

```const trends = hits.reduce((arr, curr, index, array) => {
if (arr.includes(curr)) return arr
if (curr + 1 === array[index + 1]) arr.push(curr, array[index + 1]);
return arr;
}, []);
```

The point is so that if an array contains a sequence of numbers which increase by 1 then this returns a new array with these values. For instance: `[1, 2, 3, 6, 10]` would return `[1, 2, 3]`.

The problem is: if there’s more than one sequence, I’d like to have it in a separate array (or in an array of subarrays). At this point, the function does the following `[1, 2, 3, 6, 7, 8]`. I also can’t predict how many trends there might be. How can I accomplish this?

A straightforward approach, based on two conditions whose precedence can not be changed/swapped, which actually also reads what it does …

```function collectItemSequences(list, item, idx, arr) {
if ((item - 1) === arr[idx - 1]) {
// in case of a predecessor ...

// ... push item into the most recent sequence list.
list[list.length - 1].push(item);

} else if ((item + 1) === arr[idx + 1]) {
// else, in case of a successor ...

// ... create a new sequence list with its 1st item.
list.push([ item ]);
}
return list;
}

console.log(
[2, 4, 6, 8, 10, 12, 14].reduce(collectItemSequences, [])
);
console.log(
[2, 4, 5, 6, 8, 10, 11, 12, 14].reduce(collectItemSequences, [])
);
console.log(
[1, 2, 4, 5, 6, 8, 10, 11, 12, 14, 15].reduce(collectItemSequences, [])
);```
`.as-console-wrapper { min-height: 100%!important; top: 0; }`

Based on the above approach one could implement a more generic one which allows the configuration of how to compute a current item’s sequence predecessor respectively sequence successor

```function collectItemSequencesByConditions(collector, item, idx, arr) {
const { getPredecessor, getSuccessor, list } = collector;
if (getPredecessor(item) === arr[idx - 1]) {

// push item into the most recent sequence list.
list[list.length - 1].push(item);

} else if (getSuccessor(item) === arr[idx + 1]) {

// create a new sequence list with its 1st item.
list.push([ item ]);
}
return collector;
}

const conditions = {
getPredecessor: currentItem => currentItem - 2,
getSuccessor: currentItem => currentItem + 2,
};

console.log(
[2, 4, 6, 8, 10, 12, 14].reduce(
collectItemSequencesByConditions,
{ ...conditions, list: [] },
).list
);
console.log(
[2, 4, 5, 6, 8, 10, 11, 12, 14].reduce(
collectItemSequencesByConditions,
{ ...conditions, list: [] },
).list
);
console.log(
[1, 2, 4, 5, 6, 8, 10, 11, 12, 14, 15].reduce(
collectItemSequencesByConditions,
{ ...conditions, list: [] },
).list
);```
`.as-console-wrapper { min-height: 100%!important; top: 0; }`

Edit

The OP’s Q

I set up two pair of conditions, one for item `- 1`, item `+ 1`, second pair respectively for `- 10`, `+ 10`. The hits array was `[22, 31, 32, 33, 42, 52]`. I turned your `console.logs` into `const variable = hits.reduce...` so on. Then I returned both variables. The results were `[31, 32, 33]` and `[42, 52]`. The expected outcome for second is of course `[22, 33, 42, 52]`.

Firstly the OP most probably meant `[22, 32, 42, 52]`.

Secondly …

Nope, math is reliable. And the algorithm can’t be tricked. The rules which are applied for valid predecessors/successors are merciless. Thus the “expected outcome for” `[22, 31, 32, 33, 42, 52]` and `+/- 10` of cause is `[42, 52]` and not `[22, 32, 42, 52]`.

Why?.. The second value of `[22, 31, 32, 33, 42, 52]` is `31` which breaks any possible sequence (the OP expected `22`, `32`). Thus it is not a valid predecessor/successor sequence.

Here are some test cases …

```console.log(
"for [22, 31, 32, 33, 42, 52] and [-1 , +1]",
"nexpect: '[[31,32,33]]' ?",
JSON.stringify([22, 31, 32, 33, 42, 52].reduce(
collectItemSequencesByConditions, {
getPredecessor: currentItem => currentItem - 1,
getSuccessor: currentItem => currentItem + 1,
list: [],
}
).list) === '[[31,32,33]]'
);
console.log(
[22, 31, 32, 33, 42, 52].reduce(
collectItemSequencesByConditions, {
getPredecessor: currentItem => currentItem - 1,
getSuccessor: currentItem => currentItem + 1,
list: [],
}
).list
);

console.log(
"for [22, 31, 32, 33, 42, 52] and [-10 , +10]",
"nexpect: '[[42,52]]' ?",
JSON.stringify([22, 31, 32, 33, 42, 52].reduce(
collectItemSequencesByConditions, {
getPredecessor: currentItem => currentItem - 10,
getSuccessor: currentItem => currentItem + 10,
list: [],
}
).list) === '[[42,52]]'
);
console.log(
[22, 31, 32, 33, 42, 52].reduce(
collectItemSequencesByConditions, {
getPredecessor: currentItem => currentItem - 10,
getSuccessor: currentItem => currentItem + 10,
list: [],
}
).list
);

console.log(
"for [21, 22, 32, 33, 42, 52] and [-10 , +10]",
"nexpect: '[[22,32],[42,52]]' ?",
JSON.stringify([21, 22, 32, 33, 42, 52].reduce(
collectItemSequencesByConditions, {
getPredecessor: currentItem => currentItem - 10,
getSuccessor: currentItem => currentItem + 10,
list: [],
}
).list) === '[[22,32],[42,52]]'
);
console.log(
[21, 22, 32, 33, 42, 52].reduce(
collectItemSequencesByConditions, {
getPredecessor: currentItem => currentItem - 10,
getSuccessor: currentItem => currentItem + 10,
list: [],
}
).list
);```
`.as-console-wrapper { min-height: 100%!important; top: 0; }`
```<script>
function collectItemSequencesByConditions(collector, item, idx, arr) {
const { getPredecessor, getSuccessor, list } = collector;
if (getPredecessor(item) === arr[idx - 1]) {

// push item into the most recent sequence list.
list[list.length - 1].push(item);

} else if (getSuccessor(item) === arr[idx + 1]) {

// create a new sequence list with its 1st item.
list.push([ item ]);
}
return collector;
}
</script>```