You can use findIndex to find the index in the array of the object and replace it as required:
var item = {...}
var items = [{id:2}, {id:2}, {id:2}];
var foundIndex = items.findIndex(x => x.id == item.id);
items[foundIndex] = item;
This assumes unique IDs. If your IDs are duplicated (as in your example), it's probably better if you use forEach:
items.forEach((element, index) => {
if(element.id === item.id) {
items[index] = item;
}
});
Answer from CodingIntrigue on Stack OverflowYou can use findIndex to find the index in the array of the object and replace it as required:
var item = {...}
var items = [{id:2}, {id:2}, {id:2}];
var foundIndex = items.findIndex(x => x.id == item.id);
items[foundIndex] = item;
This assumes unique IDs. If your IDs are duplicated (as in your example), it's probably better if you use forEach:
items.forEach((element, index) => {
if(element.id === item.id) {
items[index] = item;
}
});
My best approach is:
var item = {...}
var items = [{id:2}, {id:2}, {id:2}];
items[items.findIndex(el => el.id === item.id)] = item;
Reference for findIndex
And in case you don't want to replace with new object, but instead to copy the fields of item, you can use Object.assign:
Object.assign(items[items.findIndex(el => el.id === item.id)], item)
as an alternative with .map():
Object.assign(items, items.map(el => el.id === item.id? item : el))
Functional approach:
Don't modify the array, use a new one, so you don't generate side effects
const updatedItems = items.map(el => el.id === item.id ? item : el)
Note
Properly used, references to objects are not lost, so you could even use the original object reference, instead of creating new ones.
const myArr = [{ id: 1 }, { id: 2 }, { id: 9 }];
const [a, b, c] = myArr;
// modify original reference will change object in the array
a.color = 'green';
console.log(myArr[0].color); // outputs 'green'
This issue usually happens when consuming lists from database and then mapping the list to generate HTML content which will modify the elements of the list, and then we need to update the list and send it back to database as a list.
Good news is, references are kept, so you could organize your code to get advantage of it, and think about a list as an Object with identities for free, which are integers from 0 to length -1. So every time you access any property of your Object, do it as list[i], and you don't lose reference, and original object is changed. Keep in mind that this is useful when your source of truth is only one (the Object created), and your app is always consistently consuming the same Object (not fetching several times from database and assigning it to list along the lifespan of the component).
Bad news is that the architecture is wrong, and you should receive an object by ids (dictionary) if this is what you need, something like
{
1232: { id: 1232, ...},
asdf234asf: { id: 'asdf234asf', ...},
...
}
This way, you don't search in arrays, which is resource consuming. You "just access by key in the object", which is instant and performant.
javascript - Find and replace object in array (based on id) - Stack Overflow
javascript - How to find and replace an object with in array of objects - Stack Overflow
javascript - How to replace item in array? - Stack Overflow
Find and replace value inside an array of objects javascript - Stack Overflow
Use Array.map and Array.find():
const allItems = [
{ 'id': 1, 'category_id': 1, 'text': 'old' },
{ 'id': 2, 'category_id': 1, 'text': 'old' }
];
const newItems = [
{ 'id': 1, 'category_id': 1, 'text': 'new', 'more_info': 'abcd' },
{ 'id': 2, 'category_id': 1, 'text': 'new', 'more_info': 'abcd' }
];
const result = allItems.map(x => {
const item = newItems.find(({ id }) => id === x.id);
return item ? item : x;
});
console.log(result);
This can even be shortened by using a logical or to return the original item when the call to find returns undefined:
const result = allItems.map(x => newItems.find(({ id }) => id === x.id) || x);
Regarding your code, you can't use indexOf since it only compares primitive values or references in the case of arrays and objects.
Just use map like so:
const allItems = [{
'id': 1,
'category_id': 1,
'text': 'old',
},
{
'id': 2,
'category_id': 1,
'text': 'old'
}
];
const newItems = [{
'id': 1,
'category_id': 1,
'text': 'new',
'more_info': 'abcd'
},
{
'id': 2,
'category_id': 1,
'text': 'new',
'more_info': 'abcd'
}
];
const replacedItems = allItems.map(e => {
if (newItems.some(({ id }) => id == e.id)) {
return newItems.find(({ id }) => id == e.id);
}
return e;
});
console.log(replacedItems);
Different ways to achieve this.
- By using Object.assign() method. It returns the modified target object.
const data = [{
"id": 1,
"name": "January",
"abc": "abc",
"xyz": "xyz"
}, {
"id": 2,
"name": "February",
"abc": "abc",
"xyz": "xyz"
}];
const target = data.find((obj) => obj.id === 2);
const source = {
id: 2,
name: 'New Month',
abc: 'abc123',
xyz: 'someValue'
};
Object.assign(target, source);
console.log( data );
- By using array.map() method which creates a new array populated with the results of calling a provided function on every element in the calling array.
const data = [{"id": 1,"name": "January","abc": "abc","xyz": "xyz"}, {"id": 2,"name": "February","abc": "abc","xyz": "xyz"}];
const modifiedObj = {"id": 2,"name": "New month","abc": "1234abc","xyz": "someVlaue"};
const result = data.map((item) => item.id === modifiedObj.id ? modifiedObj : item);
console.log(result);
You can use Object.assign() with find() as follows:
const data = [{
"id": 1,
"name": "January",
"abc": "abc",
"xyz": "xyz"
}, {
"id": 2,
"name": "February",
"abc": "abc",
"xyz": "xyz"
}];
Object.assign(
//find the desired object
data.find(({id,name,abc,xyz}) => id === 2),
//pass these new values
{name:"New Month",abc:"abc123",xyz:"someValue"}
);
console.log( data );
var index = items.indexOf(3452);
if (index !== -1) {
items[index] = 1010;
}
Also it is recommend you not use the constructor method to initialize your arrays. Instead, use the literal syntax:
var items = [523, 3452, 334, 31, 5346];
You can also use the ~ operator if you are into terse JavaScript and want to shorten the -1 comparison:
var index = items.indexOf(3452);
if (~index) {
items[index] = 1010;
}
Sometimes I even like to write a contains function to abstract this check and make it easier to understand what's going on. What's awesome is this works on arrays and strings both:
var contains = function (haystack, needle) {
return !!~haystack.indexOf(needle);
};
// can be used like so now:
if (contains(items, 3452)) {
// do something else...
}
Starting with ES6/ES2015 for strings, and proposed for ES2016 for arrays, you can more easily determine if a source contains another value:
if (haystack.includes(needle)) {
// do your thing
}
The Array.indexOf() method will replace the first instance. To get every instance use Array.map():
a = a.map(item => item == 3452 ? 1010 : item);
Of course, that creates a new array. If you want to do it in place, use Array.forEach():
a.forEach((item, i) => { if (item == 3452) a[i] = 1010; });
You can use Array#find.
let arr = [
{
"enabled": true,
"deviceID": "eI2K-6iUvVw:APA",
},
{
"enabled": true,
"deviceID": "e_Fhn7sWzXE:APA",
},
{
"enabled": true,
"deviceID": "e65K-6RRvVw:APA",
},
];
const id = 'eI2K-6iUvVw:APA';
arr.find(v => v.deviceID === id).enabled = false;
console.log(arr);
You could use Array.reduce to copy the array with the new devices disabled:
const devices = [ /* ... */ ];
const newDevices = devices.reduce((ds, d) => {
let newD = d;
if (d.deviceID === 'eI2K-6iUvVw:APA') {
newD = Object.assign({}, d, { enabled: false });
}
return ds.concat(newD);
}, []);
You can use Array#map with Array#find.
arr1.map(obj => arr2.find(o => o.id === obj.id) || obj);
Show code snippet
var arr1 = [{
id: '124',
name: 'qqq'
}, {
id: '589',
name: 'www'
}, {
id: '45',
name: 'eee'
}, {
id: '567',
name: 'rrr'
}];
var arr2 = [{
id: '124',
name: 'ttt'
}, {
id: '45',
name: 'yyy'
}];
var res = arr1.map(obj => arr2.find(o => o.id === obj.id) || obj);
console.log(res);
Run code snippetEdit code snippet Hide Results Copy to answer Expand
Here, arr2.find(o => o.id === obj.id) will return the element i.e. object from arr2 if the id is found in the arr2. If not, then the same element in arr1 i.e. obj is returned.
There is always going to be a good debate on time vs space, however these days I've found using space is better for the long run.. Mathematics aside let look at a one practical approach to the problem using hashmaps, dictionaries, or associative array's whatever you feel like labeling the simple data structure..
var marr2 = new Map(arr2.map(e => [e.id, e]));
arr1.map(obj => marr2.has(obj.id) ? marr2.get(obj.id) : obj);
I like this approach because though you could argue with an array with low numbers you are wasting space because an inline approach like @Tushar approach performs indistinguishably close to this method. However I ran some tests and the graph shows how performant in ms both methods perform from n 0 - 1000. You can decide which method works best for you, for your situation but in my experience users don't care to much about small space but they do care about small speed.

Here is my performance test I ran for source of data
var n = 1000;
var graph = new Array();
for( var x = 0; x < n; x++){
var arr1s = [...Array(x).keys()];
var arr2s = arr1s.filter( e => Math.random() > .5);
var arr1 = arr1s.map(e => {return {id: e, name: 'bill'}});
var arr2 = arr2s.map(e => {return {id: e, name: 'larry'}});
// Map 1
performance.mark('p1s');
var marr2 = new Map(arr2.map(e => [e.id, e]));
arr1.map(obj => marr2.has(obj.id) ? marr2.get(obj.id) : obj);
performance.mark('p1e');
// Map 2
performance.mark('p2s');
arr1.map(obj => arr2.find(o => o.id === obj.id) || obj);
performance.mark('p2e');
graph.push({ x: x, r1: performance.measure('HashMap Method', 'p1s', 'p1e').duration, r2: performance.measure('Inner Find', 'p2s','p2e').duration});
}
There are many ways, try this:
const index = people.findIndex(p => p.name === newPerson.name)
if(index === -1) {
people.push(newPerson);
} else {
people[index] = newPerson;
}
Using lodash, you can find mathcing index, if user will not found indexOf will return -1, so we can check this and do like this:
const index = _.indexOf(people, { name: newPerson.name});
if (index >= 0) people.splice(index, 1, newPerson)
else people.push(newPerson)
Also, if you dont wont to use lodash you can replace index constant with:
people.findIndex(i => i.name === newPerson.name);
The following function will search through an object and all of its child objects/arrays, and replace the key with the new value. It will apply globally, so it won't stop after the first replacement. Uncomment the commented line to make it that way.
function findAndReplace(object, value, replacevalue) {
for (var x in object) {
if (object.hasOwnProperty(x)) {
if (typeof object[x] == 'object') {
findAndReplace(object[x], value, replacevalue);
}
if (object[x] == value) {
object["name"] = replacevalue;
// break; // uncomment to stop after first replacement
}
}
}
}
Working jsfiddle: http://jsfiddle.net/qLTB7/28/
Try this
function findAndReplace(object,keyvalue, name) {
object.map(function (a) {
if (a.groups[0].id == keyvalue) {
a.groups[0].name = name
}
})
}
findAndReplace(myObject,"test1" ,"test grp45");
Hi,
I have some code Im doing in google apps-scripts that involves a lot of array manipulation. Currently I have a bunch of arrays a strings and they are full of data and some of the strings are either empty strings or "x" and I need to make the empty strings and the x’s be replaced with a new string “Closed”. The length of the arrays are different every time I run the code, and the number of emptys and xs are too.
Currently I am doing this by iterating through each of the arrays and checking each value for the replaceable values and replacing the matches. This is rather slow and feels like there is probably a better solution to this. So i went looking and there are methods like find() and include() and map() that all might be of use here but I wanted to ask what the optimal way to do it would be.
Code snip:
var arr={"826", "7161", "", "", "x", "927", "hah", "hg7)", "x"}
Code here
Logger.log(arr.join(", ")Expected output:
826, 7161, Closed, Closed, Closed, 927, hah, hg7), Closed