Home > OS >  Finding the range in the array of arrays
Finding the range in the array of arrays

Time:12-07

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"
]
  • Related