簡體   English   中英

無需使用for循環即可更快地迭代JavaScript數組的方法

[英]Faster approach to iterate JavaScript array without using for loop

這是我要解析的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
        }
    }
}

我正在使用for loop遍歷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數組中的時間戳。

老實說,JavaScript中最快的循環形式是for循環,它具有您當前擁有的緩存索引。 根據您所使用的瀏覽器和計算機上的可用資源,您的性能會有很大的不同。

我相信您的應用程序存在體系結構缺陷。 您一次需要所有10000000個條目嗎? 二進制搜索將幫助您找到所需的信息(由其他人建議),但是我認為您可能不需要像嘗試執行的那樣加載和循環所有條目。

考慮按需懶惰地加載條目,而不是一次加載所有條目。 根據需要加載數據。 聽起來您當前遇到內存限制,10000000條目是要處理的大量數據(尤其是如果您有復雜對象的數組)。

我建議您研究服務人員,這些服務人員是為在瀏覽器的單獨線程中運行的更多計算/繁重任務而設計的,但是目前尚不支持它們,因此如果您要創建前端應用程序,您無需控制瀏覽器即可訪問它。

一種可能是迭代速度變慢(這樣它就不會掛起):

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;
 }
}

用例:

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

這是一個本機解決方案。 遍歷單個數據集時,我得到了大約150ms時間。

 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; 

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

 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; 

我始終使用二進制方法獲得少於10ms搜索時間。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM