2017-04-22 95 views
1

替換我有嵌套的對象,可以有任何深度的任意數量的鍵。 我想替換「。」在所有鍵(如果包含)中加上「@」我們如何以有效的方式做到這一點。查找關鍵字包含點,並用@

實施例節點的js對象

obj:{ 
     "BotBuilder.Data.SessionState": { 
      "lastAccess": 1492886892545, 
      "version": 14, 
      "callstack": [ 
       { 
        "id": "*:/", 
        "state": { 
         "BotBuilder.Data.WaterfallStep": 0, 
         "BotBuilder.Data.Intent": "welcomeDialog" 
        } 
       } 
      ] 
     } 

目前我使用硬編碼解決方案,但任何密鑰可在對象在其中包含任何電平是可能的「」我想概括的方式來解決這個問題

我的代碼:

replaceDot:function(doc){ 
    var finalobj={} 
    var finaldata={} 
    var finalcallstack=new Array(); 
    console.log("doc==>",doc) 
    var callstack=doc["data"]["BotBuilder.Data.SessionState"]["callstack"] 
    for(var i = 0; i < callstack.length; i++) { 
     var tempcallstack={} 
     if("BotBuilder.Data.WaterfallStep" in callstack[i]["state"]){ 
      tempcallstack["id"]=callstack[i]["id"] 
      var tempstate={} 
      tempstate["state"]=callstack[i]["state"] 
      tempstate["state"]["[email protected]@WaterfallStep"]=tempstate["state"]["BotBuilder.Data.WaterfallStep"] 
      tempstate["state"]["[email protected]@Intent"]=tempstate["state"]["BotBuilder.Data.Intent"] 
      delete tempstate["state"]["BotBuilder.Data.WaterfallStep"] 
      delete tempstate["state"]["BotBuilder.Data.Intent"] 
      tempcallstack["state"]=tempstate["state"]; 
      finalcallstack.push(tempcallstack); 
     } 
     else{ 
      finalcallstack.push(callstack[i]); 
     } 
    } 
    var obj={} 
    finalobj["lastAccess"]=doc["data"]["BotBuilder.Data.SessionState"]["lastAccess"] 
    finalobj["version"]=doc["data"]["BotBuilder.Data.SessionState"]["version"] 
    finalobj["callstack"]=finalcallstack; 
    obj["[email protected]@SessionState"]=finalobj 
    var secondrootobj={"[email protected]@SessionState":finalobj} 
    return secondrootobj; 
} 
+0

「任意深度處的任意數量的鍵」< - 循環訪問每個對象屬性/數組的值可能非常昂貴。這更加困難,因爲你可能在數組內的對象內部有數組等等。使用直接遞歸reduce函數可以讓你這樣做,但效率不高。你可能會發現對它進行硬編碼,就像你在這裏所做的那樣,使用for-loops和push是最有效的方法。 – d4nyll

+0

但任何數量的密鑰都可以..在任何深度..鍵名也可以是任何..這個文件我從服務器..我不能在服務器端更改.. –

回答

1

這裏是一個函數,它接受一個對象或數組,並且該對象的按鍵targetreplacement值。然後它將返回一個新對象,其中target的實例將由replacement(使用String.prototype.replace)替換爲結果對象的鍵。

var substituteKeyDeep = function(obj, target, replacement) { 
 
    // Get the type of the object. Array for arrays, Object for objects, null for anything else. 
 
    try { 
 
     var type = obj.constructor === Array ? Array 
 
      : (obj.constructor === Object ? Object : null); 
 
    } catch (err) { 
 
     // A try/catch is actually necessary here. This is because trying to access the `constructor` property 
 
     // of some values throws an error. For example `null.constructor` throws a TypeError. 
 
     var type = null; 
 
    } 
 
    
 
    if (type === Array) { 
 
     // Simply do a recursive call on all values in array 
 
     var ret = []; 
 
     for (var i = 0, len = obj.length; i < len; i++) { 
 
      ret[i] = substituteKeyDeep(obj[i], target, replacement); 
 
     } 
 
    } else if (type === Object) { 
 
     // Do a recursive call on all values in object, AND substitute key values using `String.prototype.replace` 
 
     var ret = {}; 
 
     for (var k in obj) { 
 
      ret[k.replace(target, replacement)] = substituteKeyDeep(obj[k], target, replacement); 
 
     } 
 
    } else { 
 
     // For values that aren't objects or arrays, simply return the value 
 
     var ret = obj; 
 
    } 
 
    
 
    return ret; 
 
}; 
 

 
var data = { 
 
    "BotBuilder.Data.SessionState": { 
 
     "lastAccess": 1492886892545, 
 
     "version": 14, 
 
     "callstack": [ 
 
      { 
 
       "id": "*:/", 
 
       "state": { 
 
        "BotBuilder.Data.WaterfallStep": 0, 
 
        "BotBuilder.Data.Intent": "welcomeDialog" 
 
       } 
 
      } 
 
     ] 
 
    } 
 
}; 
 

 
var dataWithRenamedKeys = substituteKeyDeep(data, /\./g, '@'); 
 

 
console.log(dataWithRenamedKeys);

注意,在示例中,替換值(/\./g)是正則表達式表達,而不是字符串。這是因爲需要使用全局修飾符(g)的正則表達式來替換對象關鍵字中出現的所有實例,而不僅僅是第一個。

編輯:快速免責聲明!如果使用具有循環引用的對象調用substituteKeyDeep,此解決方案將超出堆棧。

+0

非常感謝你,工作像魅力一樣 –