2016-02-11 3 views
1

У меня есть массив многомерных объектов:Обновление нескольких объектов в Вложенные массивы

var arr = [ 
    { 
    id: '10c', 
    name: 'item 1' 
    children: [ 
     {id: '11v', name: 'Item 1 child 1'}, 
     {id: '12c', name: 'Item 1 child 2'} 
    ] 
    }, 
    { 
    id: '13v', 
    name: 'item 2' 
    children: [ 
     {id: '26e', name: 'Item 2 child 1'}, 
     {id: '7a', name: 'Item 2 child 2'} 
    ] 
    } 
] 

и другой объект данных:

var array = [ 
    {id: '12c', name: 'New name 1'}, 
    {id: '26e', name: 'New name 2'}, 
    {id: '11v', name: 'New name 3'}, 
]; 

Если я хочу, чтобы обновить значение соответствующих объектов name в arr, на основе значения id в array, как бы это было наилучшим способом?

arr может быть более 2 уровней вложенности, поэтому я хотел бы быть в состоянии сделать это без гнезда кратного forEach

+0

https://github.com/gaearon/normalizr - это библиотека, созданная для вашего случая использования и нормализации вложенного JSON. – krs

ответ

3

Попробуйте это:

function update(items, id, name) { 
    var item; 
    for (var i = 0; i < items.length; i++) { 
     item = items[i]; 
     if (item.id === id) { 
      item.name = name; 
      return; 
     } 
     if (item.children) { 
      update(item.children, id, name); 
     } 
    } 
} 

Тогда:

update(arr, '11v', 'test'); 

Обновление по array:

array.forEach(function (item) { 
    update(arr, item.id, item.name); 
}); 
0

Используйте рекурсивное решение и использовать присущую изменчивость Javascript.

Сначала создайте плоскую карту, представляющую все объекты.

function createObjectMap(array) { 
    var map = {}; 

    array.forEach(function(obj) { 
    map[obj.id] = obj; 

    if(obj.children) { 
     Object.assign(map, createObjectMap(obj.children)); 
    } 
    }); 

    return map; 
} 

Теперь вы получили карту id -> object вы можете использовать. Они ссылаются на одни и те же измененные объекты, поэтому вы можете их мутировать и знать, что они также будут обновляться в исходной структуре данных.

function update(map, updates) { 
    updates.forEach(function(update) { 
    map[update.id].name = update.name; 
    }); 
} 

Это преобразование в O (1) время поиска означает, что вам не нужно писать какую-либо логику поиска.

0

Вы можете использовать угловой $ фильтр, чтобы сделать то же самое

//to get element 
function getFiltered(collection, obj){ 
    var filtered = $filter('filter')(collection, obj, true); 
    if(filtered[0]) 
    return filtered[0] 
    if(collection.children) 
    return getFiltered(collection.children, obj, true); 
} 

angular.forEach(array, function(element){ 
    var filtered = getFiltered(array, { id: element.id }) 
    if(filtered[0]) filtered.name = element.name; 
})