2

I have a big object array persons

persons = [{name:'john1'}, {name:'john2'},...]

I iterated the array and found the object I am interested to edit

objectToEdit = persons .find((person)=>person.name==='john1')

Now I created an edited object in immutable way (someOtherPerson = {name:'johnxx'})

objectFinal = {...objectToEdit, someOtherPerson}

Now I want to replace this objectFinal with objectToEdit in persons array, without having to traverse the array again. But doing objectToEdit =objectFinal , will just assign objectToEdited's reference to objectToEdit , without making any change in the persons array

Is there a clean way to achieve this without traversing the array?

Edit:

In this example, the object in persons jave just one key (i.e, name). This is to make question minimal. In my project, I have more than 30 keys.

asked Aug 12, 2018 at 10:22
4
  • what type is someOtherPerson? Commented Aug 12, 2018 at 10:24
  • someOtherPerson = {name:"johnxx"} as an example Commented Aug 12, 2018 at 10:24
  • an how should look like the result? Commented Aug 12, 2018 at 10:25
  • {name:'john1'} should be replace with {name:"johnxx"} in persons Commented Aug 12, 2018 at 10:28

4 Answers 4

3

If you want to edit an object in a list,in place, use Array.prototype.some

var persons = [{
 name: 'john1'
}, {
 name: 'jack5'
}]
var someOtherPerson = {
name: 'johnxx'
}
persons.some(function(person) {
 // if condition, edit and return true
 if (person.name === 'john1') {
 // use Object.keys to copy properties
 Object.keys(someOtherPerson).forEach(function(key) {
 person[key] = someOtherPerson[key]
 })
 // or use assign to merge 2 objects
 Object.assign(person, someOtherPerson);
 return true // stops iteration
 }
})
console.log(JSON.stringify(persons))

answered Aug 12, 2018 at 10:28
Sign up to request clarification or add additional context in comments.

2 Comments

Object.assign is what I was looking for. Can I say Object.assign is like destructuring operator but without losing reference? Also, I am wondering why did you suggest two other solutions which are not as clean as Object.assign(). Is there any advantage of using them over object.assign?
there is no advantage with other solutions. Object.assign will do what Object.keys does but in a single line.
3

If you want to avoid mutating the objects in the original array, you might use .findIndex instead, and reassign the item in the array at that index:

const persons = [{name:'john1'}, {name:'john2'}];
const objectToEditIndex = persons.findIndex((person) => person.name === 'john1');
const someOtherPerson = {name:"johnxx"};
persons[objectToEditIndex] = {
 ...persons[objectToEditIndex],
 ...someOtherPerson
};
console.log(persons);

answered Aug 12, 2018 at 10:26

Comments

0

Doing this:

objectFinal = {...objectToEdit, someOtherPerson}

you lose the reference to the original objectToEdit object. To edit it, you can do

`objectToEdit.value = otherValue`.

PS: Having said that, you only lose reference to the first level object. If that object, contains another object or array, you have reference to it:

objectFinal.innerObject.value = otherValue;
answered Aug 12, 2018 at 10:25

Comments

0

{name:'john1'} should be replace with {name:"johnxx"} in persons

Reassign persons to the persons-array mapped with the new value:

let persons = [{name:'john1'}, {name:'john2'}];
persons = persons.map( v => v.name === "john1" ? {name: "johnxx"} : v );
console.log(persons);

Or, if you're worried about performance, use Array.splice in combination with Array.findIndex

The findIndex method executes the callback function once for every array index 0..length-1 (inclusive) in the array until it finds one where callback returns a truthy value (a value that coerces to true). If such an element is found, findIndex immediately returns the index for that iteration.

let persons = [{name:'john1'}, {name:'john2'}];
persons.splice(persons.findIndex( v => v.name==="john1" ), 1, {name:'johnxx'});
console.log(persons);

Or use a utility method (snippet for a large array (1,000,000 elements) and with performance timer)

// replacer method
const replace = (obj, [key, value], replacement) => {
 obj.splice(persons.findIndex( v => v[key] === value ), 1, replacement);
 return obj;
}
// create a large array (this may take some extra time)
let persons = Array.from({length: 1000000}).map(v => 
 ({name: Math.floor(100000 + Math.random() * 1000000000).toString(16)}) );
// pick an entry
const someEntry = Math.floor(persons.length * Math.random());
const entry = Object.entries(persons[someEntry])[0];
console.log("before:", persons[someEntry]);
const t = performance.now();
// replacement call here
console.log("after:", replace(persons, entry, {name: "johnxx"})[someEntry]);
console.log("replacement took:", `${((performance.now() - t)/1000).toFixed(3)} sec`);

answered Aug 12, 2018 at 10:29

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.