Home > Back-end >  How to create ranges in a array of prices
How to create ranges in a array of prices

Time:11-09

I have an array of prices

I would like to group these prices into ranges if they are within 2 of each other

How do I achieve this

// present array
const array = [
   '3','5','6','12','17','22'
]

// the result I want
const array_ranges = [
   '3-6', '12',
  '17','22'
]

CodePudding user response:

Here is the longer script - at least it is more readable.

const array = ['3', '5', '6', '12', '14', '17', '22'];
const arrRange = array.reduce((acc, num, i) => {
  if (i === 0) {
    acc.push(num);
    return acc;
  }
  let range = acc[acc.length - 1].split("-");
  const last = range[range.length - 1];
  if ((num - last)<=2) {
    if (range.length === 1) range.push(num)
    else range[range.length - 1] = num;
    acc[acc.length - 1] = range.join("-")
  } else acc.push(num);
  return acc;
}, []);
console.log(arrRange)

CodePudding user response:

You could define an offset of 2 and check the last pair if the delta is greater as this offset and push a new value the result set, otherwise take the value of the first part of the last stored or value and build a new pair.

const
    array = ['3','5','6','12','17','22'],
    offset = 2,
    result = array.reduce((r, v, i, a) => {
        if (!i || v - a[i - 1] > offset) r.push(v);
        else r.push(`${r.pop().split('-', 1)[0]}-${v}`);
        return r;
    }, []);

console.log(result);

CodePudding user response:

One possible generic, configurable and re-usable approach was to implement the reducer function as function statement where the initial value is an object of two properties threshold and result where the former defines a range value's tolerance or delta to its previous/next range value and the latter featuring all created/collected range values.

The reducer does process an array of just number values; therefore a map task which assures number values only has to be executed before.

function createAndCollectNumberRanges({ threshold, result }, current, idx, arr) {
  threshold = Math.abs(threshold);

  const previous = arr[idx - 1] ?? null;
  const next = arr[idx   1] ?? null;

  if (
    previous === null ||
    previous < current - threshold
  ) {
    result.push(String(current));

  } else if (
    (next > current   threshold || next === null) &&
    previous >= current - threshold
  ) {
    result.push(`${ result.pop() }-${ current }`);
  }
  return { threshold, result };
}

console.log(
  ['3', '5', '6', '12', '17', '22']
    .map(Number)
    .reduce(createAndCollectNumberRanges, {

      threshold: 2,
      result: [],

    }).result
);
console.log(
  ['0', '3', '5', '6', '12', '14', '15', '17', '22', '23']  
    .map(Number)
    .reduce(createAndCollectNumberRanges, {

      threshold: 2,
      result: [],

    }).result
);

  • Related