在JSON对象中进行二进制搜索

时间:2013-05-08 07:31:03

标签: javascript json

我有一个像这样的JSON对象:

"time1": {
    "item1": "val1",
    "item2": "val2"
},
"time2": {
    "item1": "val3",
    "item2": "val4"
}
...

time*的值是new Date()值,以毫秒为单位,因此time*值的序列已排序。

现在我必须按时间搜索项目,如果该键不存在,我必须采用最接近的值。 我在对象中有数千个条目,我正在考虑二进制搜索,但我不知道该怎么做。

我无法使用经典方式middle = (right+left)/2,因为中间值可能是undefined。 我不能使用二叉树,因为我有一个我无法改变的定义结构。

由于

3 个答案:

答案 0 :(得分:1)

问题在于你可以对中位数进行未定义,但是最简单的形式是你可以使用中间键json.length/2,它不是最佳的但它可以工作。 接下来,您必须进行二进制搜索,同时保留每步的索引。 基本上你要检查的是索引,并决定是否按每个索引的值向右或向左移动。 如果你死路一条,搜索的时间不存在,你确实知道“邻居”,最后一次检查,if ((time_to_search - json[index-1]) > json[index+1] - time_to_search))检查它离它更近,到index-1index+1 (这是O(1)所以你很好),最终你可以返回json[index-1]json[index+1]

这对你有意义吗?

添加了一个小提琴,http://jsfiddle.net/QFTJ5/

注意:这不是一个完整的小提琴

答案 1 :(得分:0)

以下是您只读取数组中time个后缀的方法:

var json = {
  "time1": {
    "item1": "val1",
    "item2": "val2"
  },
  "time2": {
    "item1": "val3",
    "item2": "val4"
  }
}
var values = [];
for (var i in json) {
  values += i.substring(4);
}

现在,您可以对values索引进行二分查找。

答案 2 :(得分:0)

假设

var times = {
  "1367999303810": { // today at 9:48am
    "item1": "val1",
    "item2": "val2"
  },
  "1368000000000": { // today at 10am
    "item1": "val3",
    "item2": "val4"
  }
}

我会编写类似这样的代码(请修复数学!)

Live Demo

function getNearest(findTime) {
  for (var i=0;i<tArr.length;i++) {
    window.console && console.log(new Date(findTime),new Date(tArr[i]))      
    if (findTime === tArr[i]) return findTime;  // exact match
    if (findTime >= tArr[i]) break; // pinpoint
  }
  if (i==tArr.length) return -1; // nothing found
  if (i==tArr.length-1) return tArr[i];  // found the end
  // here the time to find is greater than one of the array entries
  var diff1 = Math.abs (findTime - tArr[i]),     // distance from last entry
  diff2 = Math.abs (tArr[i+1] - findTime);   // distance to next entry
   return diff1 === diff2 ? tArr[i+1] : // return the newest time
          diff2 > diff1 ? tArr[i] : tArr[i+1]; //  or the nearest
}    



var tArr = [];

for (var t in times) tArr.push(parseInt(t));
tArr.sort();
var findTime = new Date(2013,4,8,9,50,0).getTime(); // today at 9:50
var time = getNearest(findTime); 
if (time !=-1) window.console && console.log(times[time])