1

I have an array of multi dimensional objects:

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'}
    ]
  }
]

and another object of data:

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

If I want to update the name value of the respective objects in arr, based on the id value in array, how would be the best way of doing that?

arr might be more than 2 levels deep, so I would like to be able to do it without having to nest multiple forEach

1
  • github.com/gaearon/normalizr is a library made for your use case b y normalising nested JSON. Commented Feb 11, 2016 at 13:36

3 Answers 3

3

Try this:

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);
        }
    }
}

Then:

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

Updating by array:

array.forEach(function (item) {
    update(arr, item.id, item.name);
});
Sign up to request clarification or add additional context in comments.

Comments

0

Use a recursive solution and make use of the inherent mutability of Javascript.

First build up a flat map representation of all the objects.

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

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

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

  return map;
}

Now you've got a map of id -> object you can use. They reference the same mutable objects, so you can mutate them in place and know that they'll also update in the original data structure.

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

This conversion to O(1) lookup time means you don't have to write any searching logic.

Comments

0

You could use angular $filter to do the same

//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;
})

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.