2010-08-04 27 views
7

我正在尋找減少JSON數據的存儲需求,通過將它與已知的一組默認值進行對比來減少它。基本上,我想要的是jQuery的.extend()功能的逆,使得下列測試通過任意JSON兼容的對象:jQuery.extend的反轉(true,...)

function test_delta(defaults, delta) { 
    var current = $.extend(true, {}, defaults, delta); 

    QUnit.same(get_delta(current, defaults), delta); 
} 

在我開始寫我自己的get_delta(),是任何人都知道一個現有的實現?

+0

你將不得不自己處理這個問題,這是困難的(嵌套循環)方式。你可能知道。如果您的JSON數據具有任意深度,它會更有趣。 – 2010-08-04 22:11:39

+0

是的,我已經提出了一些有趣的邊緣案例;這就是爲什麼我認爲我會在自己挖掘之前詢問「SO oracle」。呃,好吧。 :-) – 2010-08-04 22:23:07

+0

開始的一個好地方是查看[jQuery源代碼](http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.js)中的jQuery.fn.extend函數。 – calvinf 2010-08-04 22:31:18

回答

1

你真正想要的是一個對象差異(erential)算法。

不太難寫 -



function diff (obj1, obj2) { 
    var delta = {}; 

    for (var x in obj1) { 
     if (obj2.hasOwnProperty(x)) { 
      if (typeof obj2[x] == "object") { 
       //recurse nested objects/arrays 
       delta[x] = diff(obj1[x], obj2[x]); 
      } 
      else { 
       //if obj2 doesn't match then - modified attribute 
       if (obj2[x] != obj1[x]) { 
        delta[x] = obj1[x]; 
       } 
      }   
     } 
     else { 
      //obj2 doesn't have this - new attribute 
      delta[x] = obj1[x]; 
     } 
    } 

    return delta; 
} 

alert( 
    JSON.stringify(
    diff({ hello : 'world', gone : 'fishing' }, 
      { hello : 'world' }) 
) 
); 

//outputs: 
{ gone : 'fishing' } 

正如你可以看到這是一個非常基本的實現 - 你可以延長該消息通過返回附加在一個單獨的對象OBJ2提供完整的差。

這段代碼沒有bug,對象原型和函數在不同的瀏覽器中處理方式不同,但它應該足以作爲數據結構的演示。

+0

我確實採取了一些措施來實現我自己的功能,但是有足夠多的不清楚的邊緣情況(特別是對於數組和刪除的屬性),我們決定只是放大數據庫列。 – 2010-12-14 01:49:04

1

嘗試類似的東西:

jQuery.extend({ 
    deltaExtend: function(deep, target, defaults, delta){ 
     var result = jQuery.extend.apply(jQuery, arguments); 
     jQuery(result).data('delta', delta); 
     jQuery(result).data('defaults', defaults); 
     return result; 
    } 
}); 

用法:

var result = $.deltaExtend(true, {}, defaults, delta); 
$(result).data('delta') //returns delta object 
$(result).data('defaults') //returns default object 

它也可以進行調整,以獲得它的N個對象的工作,只是需要多一點思考。

+0

這是一個非常有趣的想法!不幸的是,在我的情況下,'$ .extend'沒有用於創建「結果」對象。這是門戶系統,每個portlet可以定義它自己的默認設置。然後,「當前」設置將在頁面的整個生命週期內自由修改,並且當時間到了將Portlet的狀態保存回服務器時,我希望執行「盲」增量以減少存儲需求。 – 2011-02-22 18:59:48

+0

我有另一種解決方案,你支持哪些瀏覽器,哪些版本,更具體的是你支持IE 2011-02-22 22:17:13

1

我知道這與主題啓動器有點晚,但您可能需要查看來自Underscore.js的_.omit(object, *keys)函數。它就是這樣。

+0

但你怎麼知道'鑰匙'? – Bergi 2014-04-29 23:24:21

+0

密鑰來自存儲默認值的對象。 '_.keys(defaultObject)'給你一個鍵的數組。 – oley 2014-04-30 00:07:20

+0

你可能應該在你的回答中提到過......並且注意到這個方法只適用於* added *屬性,而不適用於所有*改變*的屬性。 – Bergi 2014-04-30 00:10:37