Reputation: 103
Here I have a function that finds the range of values of array if they are in sequence if they break then it simple return the element
if i've an array const array2 = [[1, 2],[1, 3],[1, 4],[3, 8],[3, 11],[6, 1],[6, 2]]
then the output should be ['1,2-4', '3,8', '3,11', '6,1-2']
my function works fine for this type of array
but if i've an array that does not have the same format, for example, initially values are in sequence, then they aren't, and then they come back in sequence, the function fails.
const array = [[1, 2],[1, 3],[1, 4],[1, 5],[1, 7],[1, 9],[1, 12],[1, 13],[1, 14],[2, 5],[2, 6],[2, 7],[10, 2],[10, 8]];
it shows the output
['1,2-14', '1,7', '1,9', '1,12', '2,5-7', '7,6-7', '8,7', '8,9', '10,2', '10,8']
instead of this
['1,2-5', '1,7', '1,9', '1,12-14', '2,5-7', '7,6-7', '8,7', '8,9', '10,2', '10,8']]
here is the code link : https://codesandbox.io/s/hopeful-allen-3okc0p?file=/src/index.js:11-174
Upvotes: 0
Views: 155
Reputation: 7616
You can do that with a .reduce()
that filters the array and builds a new array:
const array = [[1, 2],[1, 3],[1, 4],[1, 5],[1, 7],[1, 9],[1, 12],[1, 13],[1, 14],[2, 5],[2, 6],[2, 7],[10, 2],[10, 8]];
let v0;
let v1;
let result = array.reduce((newArr, row) => {
if(row[0] != v0 || row[1] != v1 + 1) {
// non-consecutive number, so push to new array
newArr.push(row[0] + ',' + row[1]);
} else {
let val = newArr[newArr.length - 1]; // get top array element
if(val.match(/,\d+$/)) { // first occurrence
val += '-' + row[1]; // add number
} else {
val = val.replace(/-\d+$/, '-' + row[1]); // replace last number
}
newArr[newArr.length - 1] = val; // update last array element
}
v0 = row[0]; // remember value for next row
v1 = row[1]; // "
return newArr;
}, []); // initialize new array to empty
console.log(result);
Output:
[
"1,2-5",
"1,7",
"1,9",
"1,12-14",
"2,5-7",
"10,2",
"10,8"
]
Upvotes: 1
Reputation: 1580
const array0 = [[1, 2], [1, 3], [1, 4], [1, 5], [1, 7], [1, 9], [1, 12], [1, 13], [1, 14], [2, 5], [2, 6], [2, 7], [10, 2], [10, 8]];
const array1 = [[1, 2],[10, 2],[1, 4],[1, 3],[1, 5],[1, 7],[1, 9],[1, 12],[1, 13],[1, 14],[2, 5],[2, 6],[2, 7],[10, 8]];
const array2 = [[1, 2],[1, 3],[1, 4],[3, 8],[3, 11],[6, 1],[6, 2]];
const array3 = [[1, 2],[1, 4],[1, 3],[1, 5],[1, 7],[1, 9],[2, 5],[2, 6],[2, 7],[10, 8]];
const createRange = arr => {
let s = null, d = 0;
return arr.sort((a, b) => a - b).reduce((p, c, i, arr) => {
d++;
if (!s) s = c;
if (arr[i + 1] - s > d) {
s === c ? p.push(s) : p.push(`${s}-${c}`);
s = null;
d = 0;
}
if (!arr[i + 1]) s === c ? p.push(s) : p.push(`${s}-${c}`);
return p;
}, []);
}
const findRangeInArr = arr => {
return arr.reduce((p, c) => {
const found = p.findIndex(p => p[0] === c[0]);
if (found !== -1) p[found][1].push(c[1]);
else p.push([c[0], [c[1]]]);
return p;
}, []).flatMap(a => createRange(a[1]).map(r => `${a[0]}, ${r}`)).sort((a, b) => Number(a.split(",")[0]) - Number(b.split(",")[0]));
}
console.log("arr0:", findRangeInArr(array0));
console.log("arr1:", findRangeInArr(array1));
console.log("arr2:", findRangeInArr(array2));
console.log("arr3:", findRangeInArr(array3));
Upvotes: 1