Итерация через указанный диапазон в js es6 map

У меня есть отсортированная структура карты JavaScript, в которой хранятся состояния объектов в зависимости от времени.
Map(key:time(inMilli), value: {object attributes})

Что мне нужно сделать, так это иметь возможность проверять карту по времени начала и окончания, чтобы получить коллекцию всех значений между ними, не повторяя всю карту.

//currently using something like this. But would like to not compare against entire map of times
let map = dataService.getTimeData()//returns map of all objects
let updates = getRange(someTime, someTime);

function getRange(start, stop){
  let foundValues = [];
  //if start is end or after end time
  if(start >== stop)return [start];

  //search map for values
  for([key,value] of map){
    if(key > start && key < stop)foundValues.push(key)
  }  
  return foundValues;
}

Я не использовал карту, но не могли бы вы просто использовать map.keys() и перебирать ее?

Jhecht 13.09.2018 20:58

да, но это все равно потребует итерации по всей карте. Я ищу способ получить два индекса и перебирать только то время, которое мне нужно.

Zachary Evans 13.09.2018 21:35

как я уже сказал, я не использовал Map, но, судя по тому, что я знаю о Maps, не думаю, что вы сможете сделать это, не просматривая весь массив.

Jhecht 13.09.2018 21:38

Да, это было мое первоначальное предположение, но я действительно надеялся, что кто-то найдет способ, лол. Я нашел библиотеку и опубликовал решение, которое позволяет это сделать и действительно удобно для хранения и извлечения данных на стороне клиента. Еще не тестировал производительность, но выглядит неплохо.

Zachary Evans 13.09.2018 21:50
0
4
537
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

function getRange(start, stop){

    let foundValues = [];

    if (start >== stop) return [start];

    for(let [key, value] of map.entries()){
        if (key > start && key < stop) {
            foundValues.push(key);
        } else {
            return foundValues;
        }
    }  
    return foundValues;
}

Вам просто нужно вернуть массив, когда время записи на карте выйдет за пределы указанного диапазона (начало и остановка), и это остановит итерацию.

function getRange(start, stop) {

  const currentArray = Array.from(map);

  let foundValues = [];
  let currentMap = currentArray.shift();

  while (currentMap[0] > start && currentMap[0] < stop && currentArray.length) {
    foundValues.push(currentMap[1]);
    currentMap = currentArray.shift();
  }

  return foundValues;

}

Используя цикл while, не будут перебираться все элементы на карте. Это будет работать, только если карта уже отсортирована.

Это похоже на то, что я придумал, но мне действительно не нужны накладные расходы на преобразование всей карты в массив. Закончил поиск библиотеки под названием jstree, в которой есть javascript TreeMap с функциями верхней и нижней границ, которые можно использовать для сегментации карты, как мне было нужно.

Zachary Evans 13.09.2018 21:39
Ответ принят как подходящий

Закончилось использованием jstreemap, TreeMap и перебора функций верхней и нижней границ. Это было действительно легко, и я рекомендую.

let map = new TreeMap();//just wanted to show that this is a TreeMap now
map = dataService.getData();

function getRange(startTime, endTime){
  let from = map.lowerBound(startTime);
  let to = map.upperBound(endTime);
  let it = from;//initialize to first value in iterator
  let foundValues = [];

  //only iterates from first object requested to last. No longer needs to search any unnecessary values. 
  while(!it.equals(to)){
    foundValues.push(it);
    it.next();
  }
  return foundValues();
}

Другие вопросы по теме