{"ScriptPreparationCode":"const reducerForGroupingConsecutiveNumbers = (accumulator, currentNumber, index) =\u003E {\r\n if (index === 0) {\r\n accumulator.push([currentNumber]);\r\n } else {\r\n const previousGroup = accumulator[accumulator.length - 1];\r\n const previousNumber = previousGroup[previousGroup.length - 1];\r\n if (currentNumber === previousNumber \u002B 1 || currentNumber === previousNumber) {\r\n previousGroup.push(currentNumber);\r\n } else {\r\n accumulator.push([currentNumber]);\r\n }\r\n }\r\n return accumulator;\r\n};\r\n\r\n/**\r\n * Will create an array of subarrays of consecutive numbers\r\n * Given: [0,1,2,5,6,9];\r\n * Returns: [[0,1,2],[5,6],[9]]\r\n */\r\nfunction createGroupingsOfConsecutiveNumbers(array) {\r\n return array.reduce(reducerForGroupingConsecutiveNumbers, []);\r\n};\r\n\r\nconst { List } = Immutable;\r\n\r\n/** Groups consecutive input values, e.g. [1, 2, 4] -\u003E [[1, 2], [4]] */\r\nfunction groupConsecutiveNumbers(inputArray) {\r\n const initialValue = List.of(List.of(Number())); // Use a non-empty initial value to avoid edge cases: https://www.conjur.org/blog/special-cases-are-a-code-smell/\r\n const groupings = inputArray\r\n .reduce((accumulator, newNumber) =\u003E {\r\n /* last(accumulator) and last(last(accumulator)) will always be defined because\r\n * 1. its initial value is an array containing an array with at least one element and\r\n * 2. we never add array with fewer than 1 elements\r\n * They can therefore be safely casted as defined */\r\n const lastSubarray = accumulator.last();\r\n const lastNumber = lastSubarray.last();\r\n\r\n const isConsecutive = newNumber === lastNumber \u002B 1 || newNumber === lastNumber;\r\n if (isConsecutive) {\r\n return accumulator.slice(0, -1).push(lastSubarray.push(newNumber));\r\n }\r\n return accumulator.push(List([newNumber]));\r\n }, initialValue)\r\n .toJS();\r\n const [initialValueGroup, ...rest] = groupings;\r\n const withoutInitialValue = [initialValueGroup.slice(1), ...rest].filter((array) =\u003E array.length \u003E 0);\r\n return withoutInitialValue;\r\n}\r\n\r\n","TestCases":[{"Name":"imperative (large arrays)","Code":"const numbersFromOneUpToTenThousandNotDivisibleByThree = [...Array(10000).keys()].filter(s =\u003E s % 3 !== 0);\r\ncreateGroupingsOfConsecutiveNumbers(numbersFromOneUpToTenThousandNotDivisibleByThree)","IsDeferred":false},{"Name":"functional (large arrays)","Code":"const numbersFromOneUpToTenThousandNotDivisibleByThree = [...Array(10000).keys()].filter(s =\u003E s % 3 !== 0);\r\ngroupConsecutiveNumbers(numbersFromOneUpToTenThousandNotDivisibleByThree)","IsDeferred":false},{"Name":"imperative (small arrays)","Code":"const smallArray = [0, 1, 2, 5, 6, 9];\r\ncreateGroupingsOfConsecutiveNumbers(smallArray)","IsDeferred":false},{"Name":"functional (small arrays)","Code":"const smallArray = [0, 1, 2, 5, 6, 9];\r\ngroupConsecutiveNumbers(smallArray)","IsDeferred":false}]}