检查JSON数组中的任何元素是否包含特定ID的最有效方法?

时间:2017-07-05 11:51:28

标签: arrays json node.js search

我正在使用Node v8.1.3

我有一个JSON数组如下:

[
  {
    "id":99,
    "name": "ABC"
  },
  {
    "id": 187,
    "name": "AXZ"
  }
]

此数组中包含 213000 e =对象。

此外,对象中的id s不是任何顺序或模式。

现在,我想查找特定id是否与数组中的任何ID匹配?什么是最快的等待?

我试过

isIdValid(id) {
    console.log(id)
    return this.list.filter((elem) => {
        return elem.id == id
    }).length > 0;
}

但这需要4秒钟。

2 个答案:

答案 0 :(得分:1)

一种选择是首先对整个列表进行排序(或将其插入二进制搜索树),这需要一些时间,但只进行一次。从那里你可以使用二进制搜索来获得更快的ID。

这是节点的示例bst代码: js-bst

此处还有一个可用于快速查询json数据列表的包:Defiant

修改

实际创建哈希表是比bst更快的解决方案;这是一个完成工作的示例代码:

data = [
    {
        "id":99,
        "name": "ABC"
    },
    {
        "id": 187,
        "name": "AXZ"
    }
]

var hashCache = {};
data.forEach(function(item){
    hashCache[item.id] = item.name
});

// Usage:
var id = '99';
var record = hashCache[id];
if (record) {
    alert(record);
} else {
    console.log('no match found');
}

您还应该考虑这个哈希表仅在ID是唯一的情况下才有效。否则,您需要在哈希表中为每个ID存储名称列表。

答案 1 :(得分:0)

这些不是“最有效的检查方式”。我在这里发布的内容仅仅是为了准备数据以便通过特定密钥进行更高性能的搜索。

同样值得考虑的是,在这个脚本中,Map可以有更好的性能,因为它是所有执行中的最后一个。轮到它时,V8内部已经进行了一些优化。因此,尝试分别运行它们以获得更好的结果。

'use strict';

////////////////////////
// GENERATE TEST DATA //
////////////////////////
const dataSet = [];
let count = 213000;
while(count--) dataSet.push({id: count});
let idToBeFound = 212999;


// //////////////////////////
// // Using Literal Object //
// //////////////////////////
console.time('creatingIndexAsLiteralObject');
const literalObjectKeyedByID = dataSet.map(item => ({[item.id]: true}));
console.timeEnd('creatingIndexAsLiteralObject');

console.time('isIdValidSeekingOnLiteralObject');
console.log('isIdValidSeekingOnLiteralObject :: Found?', isIdValidSeekingOnLiteralObject(idToBeFound, literalObjectKeyedByID));
console.timeEnd('isIdValidSeekingOnLiteralObject');
function isIdValidSeekingOnLiteralObject(id, list) {
    return !!list[id];
}

// //////////////////////
// // Using Set Object //
// //////////////////////
console.time('creatingIndexAsSetObject');
const setObject = new Set(dataSet.map(item => item.id));
console.timeEnd('creatingIndexAsSetObject');

console.time('isIdValidSeekingOnSet');
console.log('isIdValidSeekingOnSet :: Found?', isIdValidSeekingOnSet(idToBeFound, setObject));
console.timeEnd('isIdValidSeekingOnSet');
function isIdValidSeekingOnSet(id, list) {
    return list.has(id);
}

//////////////////////
// Using Map Object //
//////////////////////
console.time('creatingIndexAsMapObject');
const mapObjectKeyedByID = new Map();
dataSet.forEach(item => mapObjectKeyedByID.set(item.id));
console.timeEnd('creatingIndexAsMapObject');

console.time('isIdValidSeekingOnMap');
console.log('isIdValidSeekingOnMap :: Found?', isIdValidSeekingOnMap(idToBeFound, mapObjectKeyedByID));
console.timeEnd('isIdValidSeekingOnMap');
function isIdValidSeekingOnMap(id, list) {
    return list.has(id);
}