2013-02-07 78 views
1

設置嵌套對象的值,我想知道什麼是更新多對象集合的成員在JavaScriptJavaScript的:通過ID

這裏最好的辦法是我收集的簡化版本:

this.Steps = [ 

{ id: 1, text: "test", childSteps: 
    [ 
    { id: 2, text: "test"}, 
    { id: 3, text: "test"}, 
    { id: 4, text: "test", childSteps: 
    [ 
      { id: 10, text: "test"}, 
      { id: 11, text: "test"} 
    ]} 
    }, 
    { id: 5, text: "test"}, 
    { id: 6, text: "test"}, 
    { id: 7, text: "test"},  
    { id: 8, text: "test"}, 
    { id: 9, text: "test"} 
    ] 
} 
]; 

理想的做法是有一個函數被調用,如:

updateObjectByID(11, 'string to be set'); 

這是很容易的時候,我們只有1級對象的工作要做。但是當在多級集合上使用遞歸時,它變得更加困難。

我目前使用的是分析整個收集和建築物串像一個功能:

this.Steps[0].childSteps[3].childSteps[1].text == "string to be set" 

,然後我該字符串做eval()

我敢肯定,可能有更清潔的解決方案。

使用eval使我的課無法壓縮順便說一句。

任何幫助將不勝感激。

在此先感謝

+0

「*解析整個集合*」...然後在這之後仍然必須使用'eval'?不能相信,請告訴我們該代碼。 – Bergi

+0

Infact解析整個集合和構建字符串以更新集合成員。 – Tigoes

+0

如果我改變對象參數,它只會改變對象的引用,而不會改變我的集合,因爲當做遞歸時,我會發送childSteps作爲參考。 – Tigoes

回答

2

您可以通過ID直接訪問地圖上標註的對象:

var map = {}; 
(function recurse(steps) { 
    for (var i=0; i<steps.length; i++) { 
     var step = steps[i]; 
     map[ step.id ] = step; 
     if ("childSteps" in step) 
      recurse(step.childSteps); 
    } 
})(this.Steps); 

function updateObjectByID(id, string) { 
    map[id].text = string; 
} 

你的代碼中的註釋:你overcomplified很多。當滿足條件if(obj.id == objId)時,您已經獲得obj參考值!現在完全不需要搜索它的路徑,從中創建一個字符串,並對其進行評估。直接分配給它的財產!

function(steps, objId, value, whatParam, command) { 
    if (typeof whatParam == 'undefined') 
     whatParam = 'selected'; 
    $.each(steps, function(index, obj){ 
     if(obj.id == objId) { 
      // removed a lot of unecessary stuff 

      // not sure, looks like "value" was evaled sometimes as well 
      obj[whatParam] = value; 

     } // insert an "else" here if ids are unique 
     if (typeof obj.childSteps != 'undefined') {   
      this.setupObjectState(obj.childSteps, objId, value, whatParam, command); 
     } 
    }); 
} 
+0

woow這一個作品:)。但我真的不知道如何!?!無論如何,非常感謝你的幫助! – Tigoes

+0

它們只是引用「Steps」數組中的完全相同的對象。 – Bergi

+0

關於簡化版本...該功能正在做很多其他的事情,然後只是更新一個對象。它正在管理衝突的步驟(如果你選擇一個,則取消選擇另一個等等)。有時需要在實際找到對象之前撤消該命令。我知道這個解決方案是非常醜陋和低效的,但現在對於上面的解決方案,它將像醫院一樣乾淨。 – Tigoes

0

由於您使用ID調用updateObjectById(),因此ID必須是唯一的。爲什麼難道你不改變你的結構是這樣,那麼:

this.Steps = [ 
    { id: 1, text: "test" }, 
    { id: 2, parent: 1, text: "test" }, 
    { id: 3, parent: 1, text: "test" }, 
    { id: 4, parent: 1, text: "test" }, 
    { id: 10, parent: 4, text: "test" }, 
    { id: 11, parent: 4, text: "test" }, 
    { id: 5, parent: 1, text: "test"}, 
    { id: 6, parent: 1, text: "test"}, 
    { id: 7, parent: 1, text: "test"},  
    { id: 8, parent: 1, text: "test"}, 
    { id: 9, parent: 1, text: "test"} 
] 

這樣你就可以輕鬆地更新您的條目是這樣的:

function updateObjectByID(id, text) { 
    for(var i = 0; i < this.Steps.length; i++) { 
     if(this.Steps[i].id === id) { 
      this.Steps[i].text = text; 
      break; 
     } 
    } 
} 

具有額外屬性parent你仍然可以很容易地得到所有的孩子這樣的元素:

function getChildrenByID(id) { 
    var array = []; 
    for(var i = 0; i < this.Steps.length; i++) { 
     if(this.Steps[i].parent === id) { 
      array.push(this.Steps[i]); 
     } 
    } 
    return array; 
} 
+0

哇,這是一個效率低下的數據結構! – Bergi

+0

@Bergi:是嗎? – Amberlamps

+0

是的,不是直接通過屬性訪問任何東西,你總是必須過濾整個數組。 – Bergi

0

您必須遞歸下降您的樹結構搜索與目標「id」的對象並替換它的文本。例如:

function updateObjectByID(obj, id, text) { 
    if (!obj) return; 
    if (obj.id === id) { 
    obj.text = text; 
    } else if ((typeof(obj)==='object') && (obj.constructor===Array)) { 
    for (var i=0; i<obj.length; i++) { 
     updateObjectByID(obj[i], id, text); 
    } 
    } else if (obj.childSteps) { 
    updateObjectByID(obj.childSteps, id, text); 
    } 
} 

updateObjectByID(this.Steps, 11, 'String to be set'); 

但是,這個解決方案可以通過修剪樹來優化。

+0

請注意,'this.Steps'是一個數組,而不是「根步驟」。 – Bergi

0
function updateObjectByID(id, text) { 
    (function setText(steps) { 
     for(var i = 0; i < steps.length; i++){ 
      var step = steps[i]; 
      if(step.id === id){ 
       step.text = text; 
      } 
      if ("childSteps" in step){ 
       setText(step.childSteps); 
      } 
     } 
    })(this.Steps); 
} 

這裏是演示。 http://jsfiddle.net/qDWX8/

+0

這個看起來幾乎和Bergis一樣。除了我沒有看到地圖對象。而且這個也可以。看到這一點,我不明白爲什麼我的第一個版本的功能不工作。他們幾乎與此相同,但結果是函數作用域中的對象已更新(obj),但未在我的主集合(this.Steps)中更新。 – Tigoes