【问题标题】:Most efficient way to check if any element in a JSON array contains a specific id?检查 JSON 数组中的任何元素是否包含特定 id 的最有效方法?
【发布时间】:2017-12-09 01:50:13
【问题描述】:

我正在使用 Node v8.1.3

我有一个 JSON 数组如下:

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

这个数组中有大约 213000 个 e=objects。

另外,对象中的ids 没有任何顺序或模式。

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

我试过了

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

但这需要超过 4 秒。

【问题讨论】:

  • 每个条目的这些 id 是唯一的,还是可以有 id 重复?
  • 如果您需要多次执行此检查,那么首先从 JSON 中提取 id 并将它们放入“普通”数组中可能更有意义......这样您就可以使用 indexOf 等内置方法。然后,您还可以尝试查看首先订购该数组是否会带来任何额外的性能提升。
  • @FreemanLambda 每个条目唯一
  • 我会建议一个小的有条件的改进。而不是Array.filter 使用Array.some。 Filter 无论如何都会遍历整个数组,而 Some 可能会在找到匹配项时提前退出。
  • 虽然极大地提高了 JSON 中元素的性能,但它降低了列表下方元素的性能@FreemanLambda

标签: arrays json node.js search


【解决方案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 存储一个名称列表。

【讨论】:

  • 为什么这会比创建哈希更快?
【解决方案2】:

这些不是“最有效的检查方式”。我在这里发布只是作为参考,了解一些准备数据以通过特定键进行更高效搜索的方法。

另外值得考虑的是,在这个脚本中,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);
}

【讨论】:

    猜你喜欢
    • 2023-03-07
    • 1970-01-01
    • 2016-07-02
    • 2021-02-18
    • 1970-01-01
    • 2013-07-31
    • 2016-05-17
    • 2020-01-19
    • 2020-10-31
    相关资源
    最近更新 更多