2015-01-12 44 views
0

我需要找到最有效的方法來根據「要刪除的鍵」列表從任意嵌套的javascript對象中刪除值。即通過鍵名從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); 
}; 
+0

新增編輯 – BrightEyed

回答

0

我們可以爲原始對象創建一個查找表對象,以便在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]; 
     } 
    } 
}()); 

現在你可以調用插入功能插入鍵值:

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

,並調用忽略功能刪除對象:

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一次並對其進行硬編碼。可能與你的minify Javascript腳本一起。雖然在運行時填充它也很安靜。

+0

不用擔心,不完整的代碼是好的。我們想到了這樣的解決方案,但它不符合以下用例: obj = {a:[{b:1,c:1},{b:1,c:1},{ b:1,c:1}] ,然後忽略b或c。處理我能想到的唯一方法就是能夠將一些東西添加到忽略列表中,比如「a〜b」,它將被函數解釋爲遍歷列表。但是這會有點牽扯,因此來這裏首先要問:D – BrightEyed

+0

@ user1812406已經添加了一些關於如何處理您提供的示例的解釋。這個例子將明確我的意思。基本上查找表擁有一個父母的數組,而不是一個單一的參考。因此,使用相同密鑰的多個條目處理得很好。 –

0

好吧,想出了一個很不錯的方法。您只需製作一個與忽略對象大致相同的對象結構的忽略列表。

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}]} 
相關問題