簡體   English   中英

通過鍵名從javascript對象中刪除值列表的最有效方法

[英]Most efficient way to remove a list of values from a javascript object by keyname

我需要找到一種基於“要刪除的鍵”的列表從任意嵌套的javascript對象中刪除值的最有效方法。

var obj = {a:1, b:2, c:{d:1, e:1}};
var ignoreList = ["a","e"] (could also be ['a', 'c.e'])
removeIgnoredValues(obj, ignoreList) => {b:2, c:{d:1}}.

現在,顯然,如果您不關心效率,這很容易做到,並且到目前為止,我當前的實現一直為我服務。 但是現在,我不得不處理具有6個級別和大量數據的對象。

如果任何人都有一個很棒的解決方案或鏈接:)

干杯

編輯:當前實現看起來像這樣。 它有效(並處理循環引用)。 但是太慢了。

/**
 * Returns a sanitised string of an object, removing any functions and unwanted properties.
 * @param {int} obj. The object to be stringified
 * @param {Array[]} ignoreList. A array of object properties that should be removed.
 */
function sanitise(obj, ignoreList){
    if(obj == undefined){
        throw "Can't sanitise an undefined object"
    }
    var entry = JSON.parse(JSON.stringifyOnce(obj));
    for(var i in entry){
        if(entry.hasOwnProperty(i)){
            if(contains(ignoreList, i)){
                delete entry[i];
            } else if(typeof(entry[i]) == "object" && entry[i] != null){
                entry[i] = sanitise(entry[i], ignoreList);
            }
        }
    }
    return entry;
}

JSON.stringifyOnce = function(obj, replacer, indent){
    var printedObjects = [];
    var printedObjectKeys = [];

    function printOnceReplacer(key, value){
        var printedObjIndex = false;
        printedObjects.forEach(function(obj, index){
            if(obj===value){
                printedObjIndex = index;
            }
        });

        if ( key == ''){ //root element
             printedObjects.push(obj);
            printedObjectKeys.push("root");
             return value;
        }

        else if(printedObjIndex+"" != "false" && typeof(value)=="object"){
            if ( printedObjectKeys[printedObjIndex] == "root"){
                return "(pointer to root)";
            }else{
                return "(see " + ((!!value && !!value.constructor) ? value.constructor.name.toLowerCase()  : typeof(value)) + " with key " + printedObjectKeys[printedObjIndex] + ")";
            }
        }else{

            var qualifiedKey = key || "(empty key)";
            printedObjects.push(value);
            printedObjectKeys.push(qualifiedKey);
            if(replacer){
                return replacer(key, value);
            }else{
                return value;
            }
        }
    }
    return JSON.stringify(obj, printOnceReplacer, indent);
};

我們可以為原始對象創建一個查找表對象,以在O(1)時間內刪除任何給定的鍵。 該實現將涉及您添加自定義函數以從對象中添加/刪除對象。

(function() {
    var lookUpTable = {};
    myObj.prototype.insert = function(key, value) {
        // add key to the myObj
        // insert an Entry for parent of key in lookUpTable
        // lookUpTable = { "a" : [myObj.b, myObj, myObj.c.d.e] }
    }

    myObj.prototype.ignore = function(ignoreList) {
        for( key in ignoreList ) {
             for( parent in lookUpTable[key] )
                  delete parent[key];
             delete lookUpTable [key];
        }
    }
}());

現在,您可以調用insert函數來插入鍵值:

myObj.insert('a.b.c.d', ['p', 'g']);

並調用ignore函數刪除對象:

myObj.ignore(['d', 'e']);

抱歉,您提供的代碼不完整。 但是,您應該能夠輕松安靜地實現細節。 希望你能明白。

對於您給出的示例:

obj = {a:[{b:1, c:1}, {b:1, c:1}, {b:1, c:1}] 

而您想忽略所有的“ b”。 請注意,查找表條目的值是數組,而不僅僅是一個值。 這是忽略多個具有相同名稱的條目的強大功能。在這種情況下,“ b”的條目將是這樣的。

lookupTable = {
                  b : [           // The parent objects of 'b'
                          obj['a'][0],
                          obj['a'][1],
                          obj['a'][2]
                       ]
              }

基本上, lookuptable包含對包含鍵'b'所有對象的引用數組。 因此,您遍歷每個父對象並刪除它們的'b'條目。

$.each(lookupTable['b'], function( parent ) {
    delete parent['b']; // Deletes 'b' inside of every parent object
});

同時插入您填寫此查找表項obj或同時obj加載首次。 如果obj是硬編碼的,則還可以生成一次lookupTable並對其進行硬編碼。 可能與您的壓縮Javascript腳本一起使用。 盡管在運行時填充它也很好。

好吧,想出了一個很好的方法。 您只需創建一個與要忽略的對象具有大致相同的對象結構的忽略列表。

function ignore(obj, list){
    for(var i in list){
        var type = Object.prototype.toString.call(list[i]);

        if(type == "[object String]"){
            delete obj[i];
        } 

        else if (type == "[object Object]"){
            ignore(obj[i], list[i])
        } 

        else if (type == "[object Array]"){
            var objList = obj[i];
            var subList = list[i][0];

            for(var n in objList){
                ignore(objList[n], subList)
            }
        }
    }
}

x = {a:1, b:[{c:1, d:1}, {c:1, d:1}, {c:1, d:1}], e:1}
ignoreList = {'e':'e', 'b':[{'c':'c'}]}
ignore(x, ignoreList) => {a:1, b:[{d:1}, {d:1}, {d:1}]}

暫無
暫無

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

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