Override an object from array of objects in javascript - javascript

I have an array of object as below:
let arr = [{
id: 1,
name: 'John',
lastName: 'Smith'
},
{
id: 2,
name: 'Jill',
lastName: 'Smith'
}
];
I want to update an object with id = 1 with some properties from another object.
const obj = {
id: 1,
name: 'JOHn1'
}
The expected out is:
[{
id: 1,
name: 'JOHn1',
lastName: 'Smith'
},
{
id: 2,
name: 'Jill',
lastName: 'Smith'
}
]
I tried using Object.assign(), but it does not work. Could anyone please let me know.
arr = Object.assign(arr, obj);
thanks
thanks

You need to find the entry which you want to use as the assign target first: in this case, you need to query for the entry where id is 1. This can be done by using Array.prototype.find to locate the target, and then do Object.assign() on the target itself.
Since the found object is pass-by-reference, updating the object directly will update its entry in your array of objects directly.
See proof-of-concept below:
const arr = [{
id: 1,
name: 'John',
lastName: 'Smith'
},
{
id: 2,
name: 'Jill',
lastName: 'Smith'
}
];
const obj = {
id: 1,
name: 'JOHn1'
};
const foundObj = arr.find(({ id }) => id === obj.id);
if (foundObj) {
Object.assign(foundObj, obj);
}
console.log(arr);

Related

Convert Array of Object to Object

I have an array who look like this:
tab [
0: {
firstName: John,
lastName: Doe,
situation: married,
familyMembers: 5,
}
1: {
firstName: Jack,
lastName: Daniel,
situation: single,
familyMembers: 6,
}
]
I need something like this:
{
[John]: {[Doe]: 5,
[Jack]: {[Daniel]: 6,
}
I tried something like this:
tab.map((item) => {
return (
{[item.firstName]: {[item.lastName]: item.familyMembers}}
)
})
But even without considering that I have an array instead of an object the result look like this:
[
0: {
[John]: {[Doe]: 5,
}
1: {
[Jack]: {[Daniel]: 6,
}
]
Any suggestion here will be appreciate I tried using reduce but as I probably don't use it well it make really bad result.
Assuming, you wnat the names as keys, yxou could build the entries and from it the object.
var tab = [{ firstName: 'John', lastName: 'Doe', situation: 'maried', familyMembers: 5 }, { firstName: 'Jack', lastName: 'Daniel', situation: 'single', familyMembers: 6 }],
result = Object.fromEntries(tab.map(({ firstName, lastName, familyMembers }) =>
[firstName, { [lastName]: familyMembers }]
));
console.log(result);
map() always returns an array of the results of the function.
You can use reduce() instead
var tab = [{
firstName: 'John',
lastName: 'Doe',
situation: 'maried',
familyMembers: 5,
},
{
firstName: 'Jack',
lastName: 'Daniel',
situation: 'single',
familyMembers: 6,
}
];
var result = tab.reduce((obj, item) => {
obj[item.firstName] = {
[item.lastName]: item.familyMembers
};
return obj;
}, {});
console.log(result);

How to create a new array of objects form object without duplicates ? (ES6)

I would like to create an array of all "department" from the "users" array without duplicate in ES6.
I've tried with forEach, reduce, filter, without success...
Users array:
let users = [{
firstname: 'test',
department: {
id: 1,
name: 'hello'
}
},
{
firstname: 'test2',
department: {
id: 2,
name: 'hello2'
}
},
{
firstname: 'test2',
department: {
id: 1,
name: 'hello'
}
}
]
Result expected:
// Expected
departments = [{
id: 1,
name: 'hello'
},
{
id: 2,
name: 'hello2'
}
] */
My own experiment:
let departments = []
users.forEach(user => {
console.log('-------------------')
console.log(departments)
console.log(user)
console.log(user.department)
console.log(departments.includes(user.department))
if (!departments.includes(user.department)) {
departments.push(user.department)
}
console.log(departments)
})
console.log(departments)
Thanks for your help!
Problem:
Your problem is that you are checking for departments with Array#includes() which is rather used with primitives such as Number and string and doesn't compare objects, try not to use it as it's not compatible with IE also.
Solution:
You can do it using Array#map() and Array#filter() methods:
var deps = users.map(u => u.department);
let results = deps.filter((item, pos) => {
return deps.map(v => v.id).indexOf(item.id) == pos;
});
First map the items to keep only the department object.
Then filter the departments to exclude the ones that has the same id.
Demo:
This is a working demo:
let users = [{
firstname: 'test',
department: {
id: 1,
name: 'hello'
}
},
{
firstname: 'test2',
department: {
id: 2,
name: 'hello2'
}
},
{
firstname: 'test2',
department: {
id: 1,
name: 'hello'
}
}
];
var deps = users.map(u => u.department);
let results = deps.filter((item, pos) => {
return deps.map(v => v.id).indexOf(item.id) == pos;
});
console.log(results);
Just map to the departments, then filter out based on the id:
const ids = new Set;
const result = users
.map(user => user.department)
.filter(({ id }) => !ids.has(id) && ids.add(id));
(This is O(n) as Set lookup / insertion is O(1))
You can use Array.reduce() for that:
let users = [{
firstname: 'test',
department: {
id: 1,
name: 'hello'
}
},
{
firstname: 'test2',
department: {
id: 2,
name: 'hello2'
}
},
{
firstname: 'test2',
department: {
id: 1,
name: 'hello'
}
}
];
let departments = users.reduce((acc, obj)=>{
let exist = acc.find(({id}) => id === obj.department.id);
if(!exist){
acc.push({id:obj.department.id, name: obj.department.name});
}
return acc;
}, []);
console.log(departments);

Sum properties array of Objects [duplicate]

This question already has answers here:
Aggregating object values of JavaScript arrays?
(2 answers)
Closed 4 years ago.
I have an Array of objects, for example:
[{
name: 'mike',
id: 3312,
points: 2,
summary: 'example',
}, {
name: 'andrew',
id: 4123,
points: 1,
summary: 'example',
}, {
name: 'mike',
id: 0522,
points: 5,
summary: 'example',
}]
I need to sum the points for each person, the problem I´m facing is there are more than 50 different person names so I can´t do something like this
for (let i = 0; i < issues.length; i++) {
if (issues[i].name == 'mike') {
//////////////////////
}
}
Because the API in future can return a new Person.
You can reduce into an object indexed by name:
const input = [{
name: 'mike',
id: 3312,
points: 2,
summary: 'example',
},
{
name: 'andrew',
id: 4123,
points: 1,
summary: 'example',
},
{
name: 'mike',
id: 0522,
points: 5,
summary: 'example',
}];
const points = input.reduce((a, { name, points }) => (
Object.assign(a, { [name]: (a[name] || 0) + points })
), {});
console.log(points);
If you do not want to use reduce and keep things simple you can still use a forEach loop as below:
const input = [{
name: 'mike',
id: 3312,
points: 2,
summary: 'example',
},
{
name: 'andrew',
id: 4123,
points: 1,
summary: 'example',
},
{
name: 'mike',
id: 0522,
points: 5,
summary: 'example',
}];
var res = {};
input.forEach((obj) => {
res[obj.name] = res[obj.name] ? res[obj.name]+obj.points : obj.points;
});
console.log(res);

javascript map two nested arrays and modify the existing by lookups

I have a kids object that looks like the following:
const kids = {
name: 'john',
extra: {
city: 'London',
hobbies: [
{
id: 'football',
team: 'ABC',
},
{
id: 'basketball',
team: 'DEF',
},
],
},
};
and i have the following object that contains all sports and extra info for each.
const sports = [
{
name: 'volleyball',
coach: 'tom',
},
{
name: 'waterpolo',
coach: 'jack',
},
{
name: 'swimming',
coach: 'kate',
},
{
name: 'football',
coach: 'sara',
},
];
I want to get the list of all ids in the hobbies array and go through each of the sports items in the sports array, and found, add an extra field to that object available and give a value of true, so the result will look like:
const result = [
{
name: 'volleyball',
coach: 'tom',
},
{
name: 'waterpolo',
coach: 'jack',
},
{
name: 'swimming',
coach: 'kate',
},
{
name: 'football',
coach: 'sara',
available: true
},
];
by the way, here is my attempt:
const result = kids.extra.hobbies.map(a => a.id);
for (var key in sports) {
console.log(sports[key].name);
const foundIndex = result.indexOf(sports[key].name);
if ( foundIndex > -1) {
sports[key].available = true;
}
}
console.log(sports)
but this is too long... i am looking one liner looking code and robust logic.
This can be done many ways; however, an easy was is to divide the problem into two steps:
We can first flatten the kid's hobbies into an array by using the Array.map() function:
const hobbies = kids.extra.hobbies.map(hobby => hobby.id);
Then, we can iterate through the sports array and add an active property to any object which is present in the new hobbies array:
const result = sports.map(sport => {
if (hobbies.indexOf(sport.name) !== -1) {
sport.available = true;
}
return sport;
})
Complete Solution
const kids = {
name: 'john',
extra: {
city: 'London',
hobbies: [{
id: 'football',
team: 'ABC',
},
{
id: 'basketball',
team: 'DEF',
},
],
},
};
const sports = [{
name: 'volleyball',
coach: 'tom',
},
{
name: 'waterpolo',
coach: 'jack',
},
{
name: 'swimming',
coach: 'kate',
},
{
name: 'football',
coach: 'sara',
},
];
const hobbies = kids.extra.hobbies.map(hobby => hobby.id);
const result = sports.map(sport => {
if (hobbies.indexOf(sport.name) !== -1) {
sport.available = true;
}
return sport;
})
console.log(result);
Firstly, I would change my data structures to objects. Any time you have a list of things with unique ids, objects will make your life much easier than arrays. With that in mind, if you must use arrays, you could do the following:
const hobbies = kids.extra.hobbies
sports.forEach(s => s.available = hobbies.some(h => h.id === s.name))
Note that this mutates the original sports object (change to map for new), and also adds false/true instead of just true.
Build an array of the found sports first, then map while checking to see if the sports object's name is in it:
const kids = {name:'john',extra:{city:'London',hobbies:[{id:'football',team:'ABC',},{id:'basketball',team:'DEF',},],},}
const sports = [{name:'volleyball',coach:'tom',},{name:'waterpolo',coach:'jack',},{name:'swimming',coach:'kate',},{name:'football',coach:'sara',},];
const sportsInHobbies = kids.extra.hobbies.map(({ id }) => id);
const result = sports.map((sportObj) => {
const available = sportsInHobbies.includes(sportObj.name);
return available ? {...sportObj, available } : { ...sportObj };
});
console.log(result);

Creating new javascript Object form existing one

I have my original objects as follow. All I need is to just extract few properties from existing one and create new object.
var data = [{
id: 3,
name: Axe,
location: alkt
}, {
id: 5,
name: Roy,
location: grelad
}]
I need my output as,
var data_new = [{
id: 3,
name: Axe
}, {
id: 5,
name: Roy,
}]
How to implement in underscore js or any simple method. Possible its a large JSON object.
If there are just few properties you want to extract then simple Array.prototype.map will works fine:
var data = [{
id: 3,
name: 'Axe',
location: 'alkt'
}, {
id: 5,
name: 'Roy',
location: 'grelad'
}]
var result = data.map(function(obj) {
return {
id: obj.id,
name: obj.name
};
});
alert(JSON.stringify(result, null, 4));
Use pick in undescorejs http://underscorejs.org/#pick
Or omit http://underscorejs.org/#omit
_.pick({name: 'moe', age: 50, userid: 'moe1'}, 'name', 'age');
=> {name: 'moe', age: 50}
_.pick({name: 'moe', age: 50, userid: 'moe1'}, function(value, key, object) {
return _.isNumber(value);
});
=> {age: 50}
It you want remove each item's location
var data_new = _.map(data, function(item) {
return _.omit(item, 'location');
});
If all you want is remove properties from objects in an array, you could just delete them while iterating with forEach:
var data_new = data;
data_new.forEach(function(obj){ delete obj.location; /* or any other */ });
$scope.data_new = [];
for(i in $scope.data){
$scope.data_new.push(
{ id: $scope.data[i].id, name: $scope.data[i].name }
)
}

Categories