0

我想知道从与 JSON 对象数组匹配的巨大(数组长度接近 150 000)JSON 对象数组中获取索引的最佳方法。

目前我正在使用 for 循环来完成这项工作,但这需要 3 到 4 分钟的时间。有什么最好的方法可以提高性能吗?下面是一个说明我的要求的例子。

var hugeArray = [
    {firstName:"John", lastName:"Doe", age:21},
    {firstName:"Abraham", lastName:"Lincoln", age:46},
    {firstName:"Andy", lastName:"Crossland", age:32},
    .
    .
    .
    {firstName:"Jimmy", lastName:"Fletcher", age:65}
];

假设hugeArray的长度为150 000。我还有另一个长度为15 000的JSON数组(matchArray)。

var matchArray = [
    {firstName:"John", lastName:"Doe"},
    {firstName:"Andy", lastName:"Crossland"},
    .
    .
    .
    {firstName:"Jimmy", lastName:"Fletcher"}
];

我想要与 matchArray 匹配的 hugeArray 中的索引。

例如从上面的数据中,matchArray 有对象列表,这些对象要与hugeArray 中的对象进行匹配。如果匹配,则返回 hugeArray 的索引。上述示例的输出将如下所示。

[0,2,...,150000]

为此,我编写了一个函数,该函数返回hugeArray 的索引。如果 matchArray 对象与 hugeArray 匹配,则返回匹配的 hugeArray 的索引,否则返回 -1。

//returns -1 if no matched objects found otherwise returns index of searchArray that matched with obj.
//searchArray : Array that used to search in and return matched index.
//obj : JSON object which is used to match in with searchArray objects.
function getArrayIndex(searchArray,obj){
    var index = -1;
    for(var i=0,searchArrayLen=searchArray.length;i<searchArrayLen;i++){
        var keyMatch = true;
        for(var key in obj){
            if(obj[key].trim() !== searchArray[i][key].trim()){
                keyMatch = false;
                break;
            }
        }
        if(keyMatch){
            index = i;
            return index;
        }
    }
    return index;
}

写在 getIndexes 函数下面来调用上面的 getArrayIndex 函数。

//returns array of indexes.
function getIndexes(hugeArray,matchArray){
    var indexArray = [];
    var matchArrayLen = matchArray.length;
    for(var i=0; i<matchArrayLen; i++){
        var matchIndex = getArrayIndex(hugeArray,matchArray[i]);
        if(matchIndex !== -1){
            indexArray.push(matchIndex);
        }
    }
    return indexArray;
}

最后通过调用 getIndexes 函数,以数组格式给出所有匹配的索引。

例如,

var index = getIndexes(hugeArray,matchArray);
console.log(index);// This prints an array that contains matched indexes.
//For above data, output will be like [0,2,...,150000].
4

1 回答 1

1

您可以为此使用地图对象

let theMap = new Map(hugeArray.map((item, index) => [item.firstName + " " + item.lastName, index]));

let result = matchArray.map(item => theMap.get(item.firstName + " " + item.lastName))
  .filter(i => i !== undefined)

这假定firstNamelastName没有空格。如果它们可能包含空格,请使用另一个字符。

如果hugeArray有重复:

let theMap = new Map();
hugeArray.forEach((item, index) => {
  let key = item.firstName + " " + item.lastName;
  let value = theMap.get(key);
  if (value === undefined)
    theMap.set(key, [index]);
  else
    value.push(index);
});

let result = matchArray.flatMap(item => theMap.get(item.firstName + " " + item.lastName))
  .filter(i => i !== undefined);

hugeArray如果我们在有重复项时需要排序结果:

let result = matchArray.flatMap(item => theMap.get(item.firstName + " " + item.lastName))
      .filter(i => i !== undefined).sort();
于 2021-09-01T14:23:50.970 回答