I have an array of objects like this:
const myArr = [{id: 1, ...}, {id: 2, ...}, {id: 3, ...}];
and I have an object like this:
const myObj: {id: 2, someNewField};
I want to replace this new object for the one with the same ID in the original array, how can I do this?
I tried doing it like this:
const index = myArr.findIndex(item => item.id === myObj.id);
const filteredArr = myArr.filter(item => item.id !== myObj.id);
filteredArr.splice(index, 0, myObj);
It works but maybe there's a better way to do it
Instead of finding the index and filtering you could always use .map to return a new array.
const myObj = { id: 2, new: 1 };
const myArr = [{ id: 1 }, { id: 2 }, { id: 3 }];
const newArr = myArr.map(v => {
return v.id === myObj.id ? myObj : v;
});
It depends on what you would like to do if the item is not found in the array, as this will only replace.
By better if you mean faster method, here is one,
for(let i = 0;i<myArr.length; i++) {
if(myArr[i].id === myObj.id) {
myArr[i] = myObj;
break;
}
}
This is faster than your method because we are using for loop instead of .filter() or .findIndex() which is slower than regular for loop.
If you mean the most compact then you can do this,
myArr[myArr.findIndex(item => item.id === myObj.id)] = myObj;
Note that this approach will fail if there is no item with the given object key.
Related
Here is my array of objects
const array = [
{id: 1, data: "foo"},
{id: 1, data: "bar"},
{id: 2, data: "baz"}
]
I want to remove all duplicate objects by its id and return only the array of objects that have an unique id.
Expected result:
[
{id: 2, data: "baz"}
]
This is what I have now: O(n^2)
function getUnique(array) {
const newArray = []
for (let obj of array) {
if (array.filter(x => x.id === obj.id).length === 1) {
newArray.push(obj)
}
}
return newArray
}
Whats the more efficient way to achieve this?
Is it possible to get the time-complexity to O(n) or O(n log n)?
const array = [{
id: 1,
data: "foo"
},
{
id: 1,
data: "bar"
},
{
id: 2,
data: "baz"
}
]
let map = {};
array.forEach(x => {
map[x.id] = (map[x.id] || 0) + 1
});
console.log(array.filter(x => map[x.id] === 1))
I would suggest to count the number of occurrences in your array and store them in a Map. Next you filter all element, which count is 1
function getUnique(arr) {
const count = new Map();
arr.forEach((element) => {
count.set(element.id, (count.get(element.id) || 0) + 1);
});
return array.filter((element) => {
return count.get(element.id) === 1;
});
}
This has a runtime of 2(n) since you have to iterate over them twice
I have 2 arrays :
[{id:1,name:"name"},{id:2,name:"name2"} ,{id:3,name:"name3"}]
[{id:1,date:"123"},{id:2,date:"456"}]
Array 1 should be updated only if the id is equal :
So the array 1 will looks like
It should not create a new array . Only update the array 1 based on array 2
[{id:1,name:"name",date:"123"},{id:2,name:"name2",date:"456"} ,{id:3,name:"name3"}]
I managed to do that with for loop on array2 and inside the for filter like the following :
._filter(array1,function(item){
If(item.id=array2.id)
Do smth and update the array1.date
})
How do I doing that in he best way ? Using underscore.js
You can do something like this:
Iterate over array1 and check if the id of each item exists in array2 by using the some() method.
var arr1 = [{id:1,name:"name"},{id:2,name:"name2"} ,{id:3,name:"name3"}];
var arr2 = [{id:1,date:"123"},{id:2,date:"456"}];
var missing = [];
arr1.forEach( (item1, i) => {
var isExist = arr2.some(item2 => item2.id === item1.id)
if(!isExist) {
missing.push(i);
}
})
missing.forEach(item => {
arr2.push(arr1[item]);
})
console.log(arr2);
reference for some()
Try this :
var a = [{id:1,name:"name"},{id:2,name:"name2"} ,{id:3,name:"name3"}] ;
var b = [{id:1,date:"123"},{id:2,date:"456"}] ;
var i = 0, j = 0 ;
while( i < a.length ) {
j = 0 ;
while( j < b.length) {
if ( a[i].id === b[j].id )
Object.assign( a[i] , b[j] );
j++;
}
i++;
}
console.log(a) ;
You can use forEach to iterate over the second array and use findIndex to get the matched element from first array. If the id matches then update the object in the first array
let arr1 = [{
id: 1,
name: "name"
}, {
id: 2,
name: "name2"
}, {
id: 3,
name: "name3"
}]
let arr2 = [{
id: 1,
date: "123"
}, {
id: 2,
date: "456"
}]
arr2.forEach(function(acc) {
let findArry1Index = arr1.findIndex(function(item) {
return item.id === acc.id;
});
if (findArry1Index !== -1) {
arr1[findArry1Index].date = acc.date;
}
});
console.log(arr1)
You can do it using native language like this:
const arr1 = [{id:1,name:"name"},{id:2,name:"name2"} ,{id:3,name:"name3"}];
const arr2 = [{id:1,date:"123"},{id:2,date:"456"}];
arr1.forEach((ele) => {
const match = arr2.find(item => ele.id === item.id) || {};
Object.assign(ele, match);
});
console.log(arr1);
var a = [{id:1,name:"name"},{id:2,name:"name2"} ,{id:3,name:"name3"}];
var b = [{id:1,date:"123"},{id:2,date:"456"}];
a = _.map(a, function(e) { return _.extend(e, _.findWhere(b, {id: e.id})); });
a results in:
0: {id: 1, name: "name", date: "123"}
1: {id: 2, name: "name2", date: "456"}
2: {id: 3, name: "name3"}
However, I guess this qualifies as "creating a new array"? Maybe it can serve as an inspiration though ¯\_(ツ)_/¯
You can use underscore's indexBy function to index your second array by id, and then simply use Object.assign(...) to update your first array's elements with their corresponding match by performing a lookup in the indexed elements object.
let arr1 = [{id:1, name:"name"}, {id:2, name:"name2"}, {id:3, name:"name3"}]
let arr2 = [{id:1, date:"123"}, {id:2, date:"456"}]
const arr2Groups = _.indexBy(arr2, e => e.id);
arr1.forEach(e => Object.assign(e, arr2Groups[e.id] || {}));
console.log(arr1);
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.9.1/underscore-min.js"></script>
I have 2 array of objects:
const arr1 = [{'id':'1' 'value':'yes'}, {'id':'2', 'value':'no'}];
const arr2 = [{'id':'2', 'value':'yes'}];
So, if I try and merge these 2 arrays the result should be:
arrTemp = [{'id':'1', 'value':'yes'}, {'id':'2', 'value':'yes'}];
Basically, it should work similar to Object.assign(), but no matter what I try it does not work. Could anyone please help me in this ?
I modified the data structure. Is it possible to merge them now and get the output.
Thanks
This is how you can get the job done with ES6 spread, reduce and Object.values.
const arr1 = [{
'id': '1',
'value': 'yes'
}, {
'id': '2',
'value': 'no'
}];
const arr2 = [{
'id': '2',
'value': 'yes'
}];
const result = Object.values([...arr1, ...arr2].reduce((result, {
id,
...rest
}) => {
result[id] = {
...(result[id] || {}),
id,
...rest
};
return result;
}, {}));
console.log(result);
const result = Object.entries(Object.assign({}, ...arr1,...arr2)).map(([key, value]) => ({[key]:value}));
You could spread (...) the arrays into one resulting object ( via Object.assign) and then map its entries to an array again.
You could work with a valid ES6 data structure like a map for example:
const 1 = { 1: { string: 'yes' }, 2: { string: 'no' } }
const 2 = { 2: { string: 'yes' }, 3: { string: 'no' } }
const 3 = { ...1, ...2}
This will override your first argument with the second one or just combine them where possible.
Just try it out in your browser it's a lot easier and enhances performance since you will never have to use findById() which is an expensive operation.
In javascript, arrays are simply objects indexed by numbers starting from 0.
So when you use Object.assign on arr1 and arr2 you will override the first item in the arr1 with the first item in arr2 because they are both indexed under the key 0.
your result will be:
[
{ '2': 'yes' },
{ '2': 'no' }
]
(or in object syntax:)
{
0: { '2': 'yes' },
1: { '2': 'no' }
}
Instead of using arrays, you could create an object indexed by the number string (which is how you seem to be thinking of the array in any case).
So you could change your original data structure to make the job easier:
const arr1 = {
'1': 'yes',
'2': 'no'
};
const arr2 = {
'2': 'yes'
};
const result = Object.assign(arr1, arr2);
You could take a Map as reference to the new assigned object in the result array and build first a new array with a copy of the objects and then iterate the second array and update the objects with the same key.
var array1 = [{ 1: 'yes' }, { 2: 'no' }],
array2 = [{ 2: 'yes' }],
getKey = o => Object.keys(o)[0],
map = new Map,
result = array1.map(o => (k => map.set(k, Object.assign({}, o)).get(k))(getKey(o)));
array2.forEach(o => Object.assign(map.get(getKey(o)), o));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Array reduce could come in handy is this case. See example below:
[...arr1, ...arr2].reduce((acc, item) => {
const updated = acc.find(a => a.id === item.id)
if (!updated) {
acc.push(item)
} else {
const index = acc.indexOf(updated)
acc[index] = { ...item, ...acc[index] }
}
return acc
}, [])
simple way to add with exist array of object:
const arr1 = [{ "name":"John", "age":30, "car":"toyata" }];
const arr2 = [{ "name":"Ales", "age":40, "car":"Nissan" }];
Array.prototype.push.apply(arr1, arr2);
Result:=>
console.log(arr1)
For anyone finding this answer at a later point in time. There are a couple of ways that you could want this to work exactly, but you could filter all adjusted elements in the first array, and then combine it with the second array.
const arr3 = [...arr1.filter(item1 => !arr2.find(item2 => item1.id === item2.id)), ...arr2]
Alternatively, you could update the elements in the first array, and then filter them from the second array instead.
You cannot use array.prototype map because the key of arr1 and arr2 have the same value '2'.
You should use something like this
for (var i = 0, l = arr1.length; i < l; i++) {
var key = Object.keys(arr1[i]);
if (!arr2[key]) { arr2[key] = []; }
arr2[key].push(arr1[i][key]);
}
Regards
Let's say I have an array as follows:
types = ['Old', 'New', 'Template'];
I need to convert it into an array of objects that looks like this:
[
{
id: 1,
name: 'Old'
},
{
id: 2,
name: 'New'
},
{
id: 3,
name: 'Template'
}
]
You can use map to iterate over the original array and create new objects.
let types = ['Old', 'New', 'Template'];
let objects = types.map((value, index) => {
return {
id: index + 1,
name: value
};
})
You can check a working example here.
The solution of above problem is the map() method of JavaScript or Type Script.
map() method creates a new array with the results of calling
a provided function on every element in the calling array.
let newArray = arr.map((currentvalue,index,array)=>{
return Element of array
});
/*map() method creates a new array with the results of calling
a provided function on every element in the calling array.*/
let types = [
'Old',
'New',
'Template'
];
/*
let newArray = arr.map((currentvalue,index,array)=>{
return Element of array
});
*/
let Obj = types.map((value, i) => {
let data = {
id: i + 1,
name: value
};
return data;
});
console.log("Obj", Obj);
Please follow following links:
TypeScript
JS-Fiddle
We can achieve the solution of above problem by for loop :
let types = [
"One",
"Two",
"Three"
];
let arr = [];
for (let i = 0; i < types.length; i++){
let data = {
id: i + 1,
name: types[i]
};
arr.push(data);
}
console.log("data", arr);
is there any other way to write update an item in array of object other than below code?
const updateTodo = (list, updated) => {
const index = list.findIndex(item => item.id === update.id)
return [
...list.slice(0,index),
updated,
...list.slice(index+1)
]
}
Wait, is above function even working? https://jsbin.com/sifihocija/2/edit?js,console
The way you are doing it, is the right way to do it. However it is not working for you because in your case updated is an array and not an object and hence you only need to access the id of the first element of the array
const updateTodo = (list, updated) => {
const index = list.findIndex(item => return item.id === updated[0].id)
return [
...list.slice(0,index),
updated[0],
...list.slice(index+1)
]
}
JSBIN
However I prefer the library immutability-helper to perform any updates on the data you can do that like
import update from 'immutability-helper';
const updateTodo = (list, updated) => {
const index = list.findIndex(item => return item.id === updated[0].id)
return update(list, {
[index]: {
$set: updated[0];
}
})
}
One advantage of using immutabilty-helper is that its gives more control when the data is highly nested
You are doing to much. No need to manipulate the array if you know the index.
const items = [{id: 1, value: 1}, {id: 2, value: 2}, {id: 3, value: 3}];
items[2] = {id: 4, value: 4};
console.log(items); //last element changed
if you care about no side effects copy the array before
const items = [{id: 1, value: 1}, {id: 2, value: 2}, {id: 3, value: 3}];
const copy = items.slice();
copy[2] = {id: 4, value: 4};
return copy;
The simplest way to update(addition/deletion) an array is to use splice method.
it takes the first argument as the index, second as the no of elements you want to remove and next arguments for the addition.