更快的方法来迭代JavaScript数组而不使用for循环

时间:2017-07-11 11:18:55

标签: javascript

以下是我尝试解析的JSON数据示例。

{
    "tags": [{
        "name": "SQOP_SPD",
        "results": [{
            },
            "values": [
                [1499771383876, 0, 0],
                [1499771384800, 0, 0],
                [1499771385885, 10, 0],
                [1499771386893, 0, 0],
                [1499771388867, 0, 0],
                [1499771389879, 10, 0],
                [1499771390878, 0, 0],
                [1499771391787, 0, 0],
                [1499771392870, 0, 0],
                [1499771394015, 0, 0],
                [1499771394955, 0, 0],
                [1499771395800, 0, 0],
                [1499771396882, 0, 0],
                [1499771397904, 0, 0],
                [1499771399906, 0, 0]
            ],
            "attributes": {
                "VId": ["9499"],
            }
        }],
        "stats": {
            "rawCount": 15
        }
    }
}

我正在使用values遍历for loop数组并检查是否存在特定的时间戳。

var items = dataa['tags'][j]['results'][0]['values'];
for (var k = 0; k < items.length; k++) {
    if (items[k] == sortedTimeStampList[i]) {
          // some code
    }
}

当values数组中有10000000个条目时,页面开始挂起。

是否有更快的方法来检查values数组中的时间戳。

3 个答案:

答案 0 :(得分:1)

老实说,Javascript中最快的循环形式是for循环,具有您当前拥有的缓存索引。根据您所使用的浏览器和计算机上的可用资源,您的性能会有很大差异。

我相信你的应用程序存在架构缺陷。您是否一次需要所有10000000个条目?二进制搜索将帮助您满足您的需求(正如其他人所建议的那样),但我认为可能不需要像您尝试的那样加载和循环所有条目。

考虑延迟加载您需要的条目,而不是一次性加载。根据需要在需要时加载数据。听起来你现在正在达到内存限制,10000000条目是很多数据可以使用(特别是如果你有复杂对象的数组)。

我建议调查服务工作者,这些服务工作者是为了在浏览器的单独线程中运行的更多计算/繁重任务而制作的,但是他们还不能很好地支持它们,所以如果你选择的话可能不适合你您正在创建一个面向前端的应用程序,您无法控制哪些浏览器访问它。

答案 1 :(得分:0)

一种可能性是迭代速度较慢(因此它不会挂起):

function find(callback,value,start=0){
 for (var k = 0; k+start < items.length; k++) {
  if (items[k+start][0] === value) {
      callback(items[k+start]);
  }
  if(k==100){
   setTimeout(find,0,callback,value,start+k);
   break;
 }
}

USECASE:

find(console.log,512627172);

或者,如果您只想获得某个时间戳,可以使用地图:

var map=new Map(items.map(el=>[el[0],el.slice(1)]));
console.log(map.get(5293842838));

如果您只是想检查某个时间戳的存在,您还可以创建一个阵列的Set(更好的发现性能):

var set=new Set(items.map(el=>el[0]));
set.has(5293842838);

答案 2 :(得分:0)

这是一个原生解决方案。循环遍历单个数据集时,我得到150ms

&#13;
&#13;
var obj = {
  "tags": [{
    "name": "SQOP_SPD",
    "results": [{
      "values": [],
      "attributes": {
        "VId": ["9499"]
      }
    }],
    "stats": {
      "rawCount": 15
    }
  }]
};
//Date for timing
var d = Date.now();
//Add 10000000 rows
while (obj.tags[0].results[0].values.length < 10000000) {
  obj.tags[0].results[0].values.push([1499771383876 + obj.tags[0].results[0].values.length, 0, 0]);
}
console.log("spent " + (Date.now() - d) + "ms on adding rows");
//Native model for comparison
d = Date.now();
//Target is number 100 from the end
var target = obj.tags[0].results[0].values[obj.tags[0].results[0].values.length - 7];
//Find index
var iAmNative = obj.tags[0].results[0].values.
findIndex(function(a) {
  return a[0] == target[0];
});
//Log output
console.log("spent " + (Date.now() - d) + "ms on succeeding natively, result:", obj.tags[0].results[0].values[iAmNative], " index:", iAmNative);
obj = null;
&#13;
&#13;
&#13;

使用二分搜索方法甚至更快:

&#13;
&#13;
var obj = {
  "tags": [{
    "name": "SQOP_SPD",
    "results": [{
      "values": [],
      "attributes": {
        "VId": ["9499"]
      }
    }],
    "stats": {
      "rawCount": 15
    }
  }]
};
//Date for timing
var d = Date.now();
//Add 10000000 rows
while (obj.tags[0].results[0].values.length < 10000000) {
  obj.tags[0].results[0].values.push([1499771383876 + obj.tags[0].results[0].values.length, 0, 0]);
}
console.log("spent " + (Date.now() - d) + "ms on adding rows");
//The binary search algorithm
var binarySearch = (function() {
  /**
   * compare_complex
   *
   * @param {(number | string)} a
   * @param {(number | string)} b
   * @returns {number}
   */
  function compare_complex(a, b) {
    return a.toString().localeCompare(b.toString());
  }
  /**
   * compare_number
   *
   * @param {number} a
   * @param {number} b
   * @returns {number}
   */
  function compare_number(a, b) {
    return a - b;
  }
  /**
   * binarySearch
   *
   * @param {IBinarySearch} [args={ list: [], target: '' }]
   * @returns {number}
   */
  function binarySearch(args) {
    if (args === void 0) {
      args = {
        list: [],
        target: ''
      };
    }
    var params = {
      list: [],
      key: null,
      target: '',
      threshold: 10,
      complex: true
    };
    for (var key in args) {
      if (args.hasOwnProperty(key) && params.hasOwnProperty(key)) {
        params[key] = args[key];
      }
    }
    var max = params.list.length - 1;
    var maxKey = (params.key == null ? params.list[max] : params.list[max][params.key]);
    var min = 0;
    var minKey = (params.key == null ? params.list[min] : params.list[min][params.key]);
    if (minKey == params.target) {
      return min;
    }
    if (maxKey == params.target) {
      return max;
    }
    var compare = (params.complex === true ? compare_complex : compare_number);
    while (max - min >= params.threshold) {
      var diff = max - Math.floor((max - min) / 2);
      var diffKey = (params.key == null ? params.list[diff] : params.list[diff][params.key]);
      var cmp = compare(diffKey, params.target);
      if (cmp == 0) {
        return diff;
      } else if (cmp < 0) {
        min = diff;
      } else {
        max = diff;
      }
    }
    if (params.key != void 0) {
      var index = params.list.slice(min, max).map(function(m) {
        return m[params.key];
      }).indexOf(params.target);
    } else {
      var index = params.list.slice(min, max).indexOf(params.target);
    }
    if (index >= 0) {
      return index + min;
    }
    return index;
  }
  return binarySearch;
})();
//Binary model for comparison
d = Date.now();
//Target is number 100 from the end
var target = obj.tags[0].results[0].values[obj.tags[0].results[0].values.length - 7][0];
//Find index
var iAmBinary = binarySearch({
  list: obj.tags[0].results[0].values,
  target: target,
  key: 0
});
//Log output
console.log("spent " + (Date.now() - d) + "ms on searching binarily, result:", obj.tags[0].results[0].values[iAmBinary], "index:", iAmBinary);
//Release memory
obj = null;
&#13;
&#13;
&#13;

我一直使用二进制方法获得的搜索时间少于10ms