最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Find upper and lower boundaries in array - Stack Overflow

programmeradmin1浏览0评论

I am trying to get the upper and lower boundaries of a numeric value in an array.

const boundaries = [15, 30, 45, 60, 75, 90];
const age = 22;

For the above example, the oute should be:

[15, 30]

If for example the value is a boundary, it would bee the lower value in the oute array. If it is the max boundary or above, it should bee the max value.

Example outes:

15 => [15, 30]
22 => [15, 30]
30 => [30, 45]
90 => [90]

I tried mapping through the array and if the age is higher => return boundary. Then filter out the boundaries and calculate the indexes, but this doesn't feel like the correct way to acplish this.

const boundaries = [15, 30, 45, 60, 75, 90];
const age = 22;

// get all lower values
const allLower = boundaries.map((b) => age > b ? b : null).filter(x => x);
const lower = allLower[allLower.length - 1]; // get lowest
const upper = boundaries[boundaries.indexOf(lower) + 1]; // get next

const result = [lower, upper]; // form result

console.log(result);

I am trying to get the upper and lower boundaries of a numeric value in an array.

const boundaries = [15, 30, 45, 60, 75, 90];
const age = 22;

For the above example, the oute should be:

[15, 30]

If for example the value is a boundary, it would bee the lower value in the oute array. If it is the max boundary or above, it should bee the max value.

Example outes:

15 => [15, 30]
22 => [15, 30]
30 => [30, 45]
90 => [90]

I tried mapping through the array and if the age is higher => return boundary. Then filter out the boundaries and calculate the indexes, but this doesn't feel like the correct way to acplish this.

const boundaries = [15, 30, 45, 60, 75, 90];
const age = 22;

// get all lower values
const allLower = boundaries.map((b) => age > b ? b : null).filter(x => x);
const lower = allLower[allLower.length - 1]; // get lowest
const upper = boundaries[boundaries.indexOf(lower) + 1]; // get next

const result = [lower, upper]; // form result

console.log(result);

Is there a shorter / better / more reliable way to do this?

Share Improve this question edited Jun 21, 2021 at 8:27 axtck asked Jun 21, 2021 at 8:02 axtckaxtck 3,9653 gold badges16 silver badges32 bronze badges 8
  • what result do you expect with age = 30? what about 15 and 90? – Nina Scholz Commented Jun 21, 2021 at 8:06
  • @NinaScholz 30 => [30, 45] and 15 = [15], 90 = [90], I will update my question. – axtck Commented Jun 21, 2021 at 8:09
  • @NinaScholz actually 15 should bee [15, 30] also, excuse me – axtck Commented Jun 21, 2021 at 8:15
  • What's the rule behind the result [15,30]? Why not [15,15]? – Nico Haase Commented Jun 21, 2021 at 8:18
  • why for 15 not 30 as well? – Nina Scholz Commented Jun 21, 2021 at 8:18
 |  Show 3 more ments

5 Answers 5

Reset to default 5

Why do you use the indices for this? What if the boundaries array is not sorted? Wouldn't it be easier to filter the lists to allLower and allUpper (containing the values below and above the threshold), and then use min and max on the resulting arrays?


Sample code:

const boundaries = [15, 30, 45, 60, 75, 90];
const age = 22;

const allLower = boundaries.filter(x => x < age);
const allUpper = boundaries.filter(x => x > age);

const lowerBound = Math.max(...allLower);
const upperBound = Math.min(...allUpper);

Looks like a good use case for reduce:

const boundaries = [15, 30, 45, 60, 75, 90];


for (let search of [1, 22, 30, 90, 100]) {

    let [low, upr] = boundaries.reduce(([low, upr], x) =>
        [
            x <= search ? Math.max(low, x) : low,
            x >  search ? Math.min(upr, x) : upr,

        ],
        [-Infinity, +Infinity]
    )

    console.log(low, '<=', search, '<', upr)

}

This doesn't require boundaries to be sorted. If they always are, you might consider binary search to locate the lower bound.

Looks like a plain for-loop might help you out ;)

function getBounds(age) {
  for (let i = 0; i < boundaries.length; i++) {
    if (boundaries[i] <= age && (boundaries[i + 1] ?? Infinity) > age) {
      return boundaries.slice(i, i + 2);
    }
  }
}

You could check the previous value and next value and filter the array.

const
    getLowerUpper = (array, pivot) => array
        .filter((v, i, { [i - 1]: prev, [i + 1]: next }) =>
            v <= pivot && next > pivot ||
            prev <= pivot && v >= pivot ||
            prev === undefined && next > pivot ||
            prev < pivot && next === undefined
        ),
    boundaries = [15, 30, 45, 60, 75, 90];

console.log(...getLowerUpper(boundaries, 22));  // between
console.log(...getLowerUpper(boundaries, 30));  // direct and next
console.log(...getLowerUpper(boundaries, 10));  // lowest
console.log(...getLowerUpper(boundaries, 15));  // direct and next
console.log(...getLowerUpper(boundaries, 90));  // highest
console.log(...getLowerUpper(boundaries, 100)); // highest

You can reduce the array, something like this:

const boundaries = [15, 30, 45, 60, 75, 90];

const getResult = (array, target) => {
  if (target < array[0] || target > array[array.length - 1]) {
    return [];
  }
  return array.reduce((a, c) => {
    if (c <= target) {
      a[0] = c;
    } else if (c > target && (!a[1] || c < a[a.length - 1])) {
      a[a.length] = c;
    }
    return a;
  }, []);
}

console.log(getResult(boundaries, 22));
console.log(getResult(boundaries, 15));
console.log(getResult(boundaries, 30));
console.log(getResult(boundaries, 90));
console.log(getResult(boundaries, 14));
console.log(getResult(boundaries, 91));

发布评论

评论列表(0)

  1. 暂无评论