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
CodePudding user response:
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));
CodePudding user response:
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) {
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];
v1 = row[1];
return newArr;
}, []);
console.log(result);
Output:
[
"1,2-5",
"1,7",
"1,9",
"1,12-14",
"2,5-7",
"10,2",
"10,8"
]