JavaScript сравнивает число с ключами объекта и получает значение наименьшего - PullRequest
0 голосов
/ 06 ноября 2018

Скажем, у нас есть:

const list = {
  1: "a",
  10: "b",
  20: "c",
  30: "d",
  40: "e"
};

const value = 15;

как я могу эффективно сравнить значение с ключами объекта и получить значение соответствующего меньшего диапазона? и в этом примере ожидаемый ответ b, потому что 15 между 10 и 20.

Я хотел пойти по этому пути:

for(var i=0; i < keys.length; i++){
    const item = parseInt(keys[i],10);
    if (item == keys[i]) {
      return keys[i];
    }
  }

но это не эффективно ...

Ответы [ 5 ]

0 голосов
/ 06 ноября 2018

Вы также можете sort клавиши и затем использовать reduce, чтобы найти нижнюю клавишу целевого диапазона:

const list = {
  1: "a",
  10: "b",
  20: "c",
  30: "d",
  40: "e"
};

const value = 15;
const answer = list[Object.keys(list)
                     .map(a => parseInt(a))
                     .sort((a, b) => a - b)
                     .reduce((acc, curr) => (acc < value && value < curr) ? acc : curr)];
                     
console.log(answer);
0 голосов
/ 06 ноября 2018

Если ключи предварительно отсортированы, как в вашем примере, используйте двоичный поиск в log (n) сложности времени. Подвох в том, что сброс ключей в массив - это однократный линейный шаг (и при необходимости однократная сортировка будет O (n log n)), поэтому стоит подумать, планируете ли вы выполнять несколько поисков на одной структуре.

const bisect = (a, target, lo=0, hi=a.length-1) => {
  while (lo <= hi) {
    const mid = ~~((hi - lo) / 2 + lo);

    if (a[mid] === target) {
      return a[mid];
    }
    else if (a[mid] < target) {
      lo = mid + 1;
    }
    else {
      hi = mid - 1;
    }
  }
  
  return a[~~((hi-lo)/2+lo)];
};

const list = {
  1: "a",
  10: "b",
  20: "c",
  30: "d",
  40: "e"
};

const keys = Object.keys(list);
console.log(list[bisect(keys, 15)]);
console.log(list[bisect(keys, 16)]);
console.log(list[bisect(keys, -50)]);
console.log(list[bisect(keys, 50)]);
0 голосов
/ 06 ноября 2018

Вы можете использовать Array.findIndex(), чтобы найти 1-й индекс, который выше значения. Если ничего не найдено (возвращаемое значение равно -1), возьмите элемент в последнем ключе, иначе примите значение в keys[index - 1. Если значение меньше 1-го ключа, оно вернет undefined.

const findLowerClosest = (value, arr) => {
  const keys = Object.keys(list);
  const index = keys.findIndex(key => +key > value);
  const atKey = index !== -1 ? index - 1 : keys.length - 1;
  return arr[keys[atKey]];
}

const list = { 1: "a", 10: "b", 20: "c", 30: "d", 40: "e" };

console.log(findLowerClosest(15, list)); // b
console.log(findLowerClosest(75, list)); // e
console.log(findLowerClosest(-3, list)); // undefined
0 голосов
/ 06 ноября 2018

Вы можете использовать filter, чтобы получить значения меньше 15, затем сделать Math.max, а затем использовать это в качестве ключа для получения значения из объекта

const list = {
  1: "a",
  10: "b",
  20: "c",
  30: "d",
  40: "e"
};

const value = 15;

function getVal(n) {
  let getKeys = Math.max.apply(null, Object.keys(list).filter((item) => {
    return item < n
  }));
  return (list[getKeys])
}
console.log(getVal(value))
0 голосов
/ 06 ноября 2018

Вы можете использовать Object.keys, который получит все ключи объекта в новом массиве, и в .some (как предложено @Keith) остановить цикл (return true), когда текущее значение становится больше, чем value, ваш результат будет храниться в previous var

const list = {
  1: "a",
  10: "b",
  20: "c",
  30: "d",
  40: "e"
};

const value = 15;
let previous = 0;

Object.keys(list).some(k => {
  if (k > value) {
    return true;
  } 
  previous = k
});

console.log(list[previous]);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...