0

配列の重複排除と検索に使用される 2 つの関数があります。些細なことです。場合によっては、約 100 要素を超える配列の場合、これらの関数を使用すると大量のメモリ リークが発生し、node.js JavaScript アプリが停止することに気付きました。

私の配列 arr で何が「間違っている」可能性がありますか?それは、配列のシリアル化されたバージョンを逆シリアル化してメモリリークを修正することを意味しますか? また、ターゲット配列のシリアル化されたコピーを逆シリアル化すると、メモリ リークの問題が修正されるのはなぜですか?

おそらく関連しています:

arr は、数十回の concat 呼び出しで構築されています。

検索機能:

function findObjInArray(arr, obj, lookupKeyChain){
    var tmpObj = undefined;
    for(var i = 0; i < arr.length; i++){
        tmpObj = arr[i];
        for(var j = 0; j < lookupKeyChain.length; j++){
            tmpObj = tmpObj[lookupKeyChain[j]]
            if(!tmpObj){
                break;
            }else if(j==lookupKeyChain.length-1){
                if(tmpObj==obj){
                    return arr[i];
                }
            }
        }
    }
    return undefined;
}

重複除外機能:

function combineProducts(productList, idKey){
    var deDupedProducts = []
    for(var i = 0; i < productList.length; i++){
        var precedent = findObjInArray(deDupedProducts, productList[i][idKey], [idKey]);
        if(precedent){
            //just add tag data to precedent
            for(var j = 0; j < productList[i].tags.length; j++){
                precedent.tags.push(productList[i].tags[j]);
            }
        }else{
            deDupedProducts.push(productList[i]);
        }
    }
    return deDupedProducts;
}

arr の構造の例:

    [
        {
            "price": "$9.99",
            "name": "Big Widgets",
            "tags": [
                {
                    "tagClass": "Category",
                    "tagName": "On Sale"
                }
            ]
        },
        {
            "price": "$5.00",
            "name": "Small Widgets",
            "tags": [
                {
                    "tagClass": "Category",
                    "tagName": "On Sale"
                },

            ]
        },
        ...
    ]

メモリ リークの原因となる呼び出し:

combineProducts(
    arr,
    "name"
)

問題を修正し、正しい結果を得た呼び出し:

combineProducts(
    JSON.parse(JSON.stringify(arr)),
    "name"
)
4

1 に答える 1

1

無関係ですが、オブジェクトベースのアルゴリズムは、拡大し続ける線形検索よりも大きなリストに対してはるかに効率的 (かつ簡潔) です。

function combineProducts(productList, idKey) {
    var lookup = {};

    productList.forEach(function(product) {
        var precedent = lookup[product[idKey];

        if (precedent) {
            precedent.tags = precedent.tags.concat(product.tags);
        }
        else {
            lookup[product[idKey]] = product;
        }
    });

    return Object.keys(lookup).map(function(idValue) {
        return lookup[idValue];
    });
}

関数との唯一の違いは、順序付けが保持されないことです (データが最初から順序付けられていた場合はidKey、シングルパス アルゴリズムの方が優れています)。

于 2012-09-18T09:13:35.910 に答える