2014-08-29 236 views
1

我有一個可以具有任意長度和任意深度的對象數組。我需要能夠通過它的id找到一個對象,然後修改該數組中的對象。有沒有一種有效的方法來做到這一點與lodash或純js?在javascript數組中查找並修改深度嵌套對象

以爲可以創建索引,導致了對象但構建表達與這些索引訪問該對象似乎過於複雜/不必要

EDIT1的陣列;感謝所有你的答覆,我會盡力而且更具體。我目前正在找到我想要修改的對象的位置。父母是目標對象每個父母的ID數組。祖先可能是這個陣列的一個更好的名字。 costCenters是包含我想要修改的對象的對象數組。此功能遞歸,並返回指標,導致我想修改

var findAncestorsIdxs = function(parents, costCenters, startingIdx, parentsIdxs) { 
      var idx = startingIdx ? startingIdx : 0; 
      var pidx = parentsIdxs ? parentsIdxs : []; 

      _.each(costCenters, function(cc, ccIdx) { 
       if(cc.id === parents[idx]) { 
        console.log(pidx); 
        idx = idx + 1; 
        pidx.push(ccIdx); 
        console.log(pidx); 
        pidx = findAncestorsIdx(parents, costCenters[ccIdx].children, idx, pidx); 
       } 
      }); 
      return pidx; 
     }; 

現在有了這個數組索引如何定位和修改確切的對象我想要的對象的數組?我已嘗試這其中的祖先是索引的陣列,costCenters是與所述對象的數組修改和父是新值將被分配給所述目標對象

var setParentThroughAncestors = function(ancestors, costCenters, parent) { 
      var ccs = costCenters; 
      var depth = ancestors.length; 
      var ancestor = costCenters[ancestors[0]]; 
      for(i = 1; i < depth; i++) { 
       ancestor = ancestor.children[ancestors[i]]; 
      } 
      ancestor = parent; 
      console.log(ccs); 
      return ccs; 
     }; 

這顯然只是返回未修改costCenters數組,所以我可以看到的唯一另外一種方式是構造像myObjects [idx1] .children [2] .grandchildren [3] .ggranchildren [4] .something = newValue這樣的表達式。這是唯一的方法嗎?如果是的話,那麼最好的辦法是什麼?

+0

你必須對所有對象遞歸遍歷和比較對您正在尋找的ID。 – 2014-08-29 13:28:23

+0

你說你有一個對象數組。 JavaScript中的數組是索引的,而不是關聯的,所以大概你的意思是通過它的索引找到一個對象,而不是ID。否則,請澄清。 – Utkanos 2014-08-29 13:28:42

+0

數組中的每個對象都有一個唯一的ID。我想通過該ID找到給定的對象,然後更改該對象 – Ir1sh 2014-08-29 13:33:16

回答

2

正如Felix Kling所說,您可以對所有對象進行遞歸迭代。

// Overly-complex array 
var myArray = { 
    keyOne: {}, 
    keyTwo: { 
     myId: {a: '3'} 
    } 
}; 
var searchId = 'myId', // Your search key 
    foundValue, // Populated with the searched object 
    found = false; // Internal flag for iterate() 

// Recursive function searching through array 
function iterate(haystack) { 
    if (typeof haystack !== 'object' || haystack === null) return; // type-safety 
    if (typeof haystack[searchId] !== 'undefined') { 
     found = true; 
     foundValue = haystack[searchId]; 
     return; 
    } else { 
     for (var i in haystack) { 
      // avoid circular reference infinite loop & skip inherited properties 
      if (haystack===haystack[i] || !haystack.hasOwnProperty(i)) continue; 

      iterate(haystack[i]); 
      if (found === true) return; 
     } 
    } 
} 

// USAGE/RESULT 
iterate(myArray); 
console.log(foundValue); // {a: '3'} 
foundValue.b = 4; // Updating foundValue also updates myArray 
console.log(myArray.keyTwo.myId); // {a: '3', b: 4} 

所有JS對象分配都作爲JS中的引用傳遞。請參閱this瞭解關於對象的完整教程:)

編輯:感謝@torazaburo爲更好的代碼提供建議。

+0

感謝您的回覆,但是這個dosnt告訴我如何修改找到的對象 – Ir1sh 2014-08-29 14:15:14

+1

您直接修改foundValue,因爲它只是對myArray的引用。看到我上面更新的「RESULT」部分。 – NicolaeS 2014-08-29 14:18:47

+1

確定即時消息與你一樣謝謝我會試試看看我該怎麼去 – Ir1sh 2014-08-29 14:23:59

10

您可以使用JSON.stringify。它爲每個訪問過的鍵/值對(任意深度)提供回調,並具有跳過或替換的功能。

下面的函數返回一個搜索與指定的ID的對象,並調用在其上的指定的變換的回調函數:

function scan(id, transform) { 
    return function(obj) { 
    return JSON.parse(JSON.stringify(obj, function(key, value) { 
     if (typeof value === 'object' && value !== null && value.id === id) { 
     return transform(value); 
     } else { 
     return value; 
     } 
    })); 
} 

如果作爲問題指出,你有對象的數組,和一個在每個對象,其包含對象被加以修飾,和變換函數的陣列的id平行陣列,那麼它只是一個包裹如上

for (i = 0; i < objects.length; i++) { 
    scan(ids[i], transforms[i])(objects[i]); 
} 

的物質由於對JSON.stringify限制,這種方法將如果t失敗這裏是對象中的循環引用,如果你在意的話,省略函數,正則表達式和符號鍵屬性。

請參閱https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_native_JSON#The_replacer_parameter瞭解更多信息。

+3

不錯!不知道'JSON.stringify'可以接受回調。 – Hrishi 2014-08-31 04:18:10

+1

這是非常有用的信息。我希望在花費了一段令人尷尬的長時間試圖遍歷一個帶有一個持久變換器的對象樹來尋找日期字符串以轉化爲Date對象之前,我發現它! – 2016-07-17 04:17:11

0

如果每個對象都有與存儲其它嵌套對象相同的名稱屬性,可以使用:https://github.com/dominik791/obj-traverse

findAndModifyFirst()方法應該解決您的問題。第一個參數是一個根對象,而不是數組,那麼你應該先創建它:

var rootObj = { 
    name: 'rootObject', 
    children: [ 
    { 
     'name': 'child1', 
     children: [ ... ] 
    }, 
    { 
     'name': 'child2', 
     children: [ ... ] 
    } 
    ] 
}; 

然後使用findAndModifyFirst()方法:

findAndModifyFirst(rootObj, 'children', { id: 1 }, replacementObject) 

replacementObject是什麼對象,應該替換具有id對象等於1

可以使用演示應用程序嘗試: https://dominik791.github.io/obj-traverse-demo/

相關問題