【问题标题】:Binary search in JSON objectJSON对象中的二进制搜索
【发布时间】:2013-05-08 07:31:03
【问题描述】:

我有一个这样的 JSON 对象:

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

time*的值是new Date()的值,单位是毫秒,所以time*的值的顺序是排序的。

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

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

谢谢

【问题讨论】:

  • 将值读入数组? (由timevalue - firstTimeValue 索引)
  • 你能举一个“时间价值*”的实际例子吗 - JSFiddle.net 会很棒
  • 请记住,对象中属性的顺序是not guaranteed,因此您必须先将其转换为数组,然后才能进行有意义的二分搜索。从那里开始,它非常简单。
  • time* 的值类似于 1368000928818。例如,一些连续的值是 1368000928818、1368000938821、1368000948821 和 1368000958824。您可以看到这些值之间没有共同的差异。
  • “最近的值”,还是“匹配或下一个最小值”?后者更容易一些......

标签: javascript json


【解决方案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/

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

【讨论】:

  • 这有道理,但 json.length 返回undefined
  • 对,你得用这个Object.keys(json).length
【解决方案2】:

这是您如何只读取数组中的 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 索引进行二分搜索。

【讨论】:

  • 复制所有项目没用...此时我可以遍历所有元素并直接搜索我要查找的项目,但这会很耗时(因为复制数组)跨度>
  • @MaxMarkson 我不会复制所有项目 - 只是构建您感兴趣的数字的数组。我不确定它是否会对性能产生影响(实际上我觉得这是一个更简单的数据结构,搜索会更快)。另一方面,通过我的建议,代码肯定会变得更容易理解。毕竟它是你打电话,虽然
【解决方案3】:

假设

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])

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-22
    • 2022-01-18
    • 2014-03-10
    • 1970-01-01
    • 1970-01-01
    • 2018-08-04
    • 1970-01-01
    相关资源
    最近更新 更多