How can I keep same object but replace only one property? - javascript

Let's say this is my array of objects:
let data = [{
firstname: 'John',
lastname: 'Doe'
},
{
firstname: 'Jane',
lastname: '- Doe'
}]
Now, I want to make a new object, but where - Doe is I need to remove this part - and leave only Doe.
I have tried this:
let pollyData = data.map(item => _.mapValues(item, val => val.lastname.split('- ').pop()))
However, I get undefined.
Is there a better way to achieve this?
Thanks.

Iterate with Array#map. Check if an object includes a lastname with a dash. If so create a new object with a cleaned lastname. If not return the original object.
Note: I've used object spread to replace the lastname. If not supported by your build stack, you can use Object.assign({}, obj, { lastname: obj.lastname.replace(/^-\s+/, '') }) instead.
const data = [{
firstname: 'John',
lastname: 'Doe'
},
{
firstname: 'Jane',
lastname: '- Doe'
}
];
const result = data.map((obj) => obj.lastname.includes('-') ? ({
...obj,
lastname: obj.lastname.replace(/^-\s+/, '')
}) : obj);
console.log(result);

You can use regex and array#map
let data = [{ firstname: 'John', lastname: 'Doe' }, { firstname: 'Jane', lastname: '- Doe' }];
var result = data.map(({firstname, lastname}) =>
({firstname, lastname: lastname.replace(/^\s*\-\s*/g, '')})
);
console.log(result);

Related

Js ES6, Merge 2 objects and store in array instead replacing existent key

i have the following
let user = { name: 'John', lastName: 'Doe', phone: '000111222' };
let otherInfo = { phone: '123456', age: '30' };
After merging both
let result = { ...user, ...otherInfo };
I got
{ name: 'John', lastName: 'Doe', phone: '123456', age: '30' };
Base on this, the phone is duplicated entry, i want to keep the old phone and keep both in array, based on ES6 spread, note: (i can do iterating object, but is better to write less code)
{ name: 'John', lastName: 'Doe', phone: ['000111222', '123456'], age: '30' };
Some ideas?, thank you in advance.
Merge the objects together, and get all unique keys with Object.keys(). Reduce the keys, and check if the key exists in the objects. If it exists in both of them, combine the values to an array. If it doesn't take the value from one of the objects:
const fn = (o1, o2) => Object.keys({ ...o1, ...o2 }) // get combined keys
.reduce((acc, key) => {
// if key exists it both object combine the values in an array
if (key in o1 && key in o2) acc[key] = [o1[key], o2[key]];
// take the value from o1 or o2
else acc[key] = key in o1 ? o1[key] : o2[key];
return acc;
}, {});
const user = { name: 'John', lastName: 'Doe', phone: '000111222' };
const otherInfo = { phone: '123456', age: '30' };
const result = fn(user, otherInfo);
console.log(result);
You can do this:
let result = { ...user, ...otherInfo, phone: user.phone && otherInfo.phone ? [user.phone, otherInfo.phone]: user.phone || otherInfo.phone };
For a generic solution, where you would maybe need to merge more than two objects, you could apply Object.entries on each of the objects and create a flat array of the resulting pairs. Then use these pairs to extend the result object. When a pair references a key that is already in the result object, use [].concat to silently merge that value with the new value into an array. This also works if the stored value was already an array with two or more previously found values.
Here is a snippet:
const user = { name: 'John', lastName: 'Doe', phone: '000111222' };
const otherInfo = { phone: '123456', age: '30' };
const moreInfo = { phone: '9876543', hometown: 'Paris' };
let res = {};
for (let [k, v] of [user, otherInfo, moreInfo].flatMap(Object.entries)) {
res[k] = k in res ? [].concat(res[k], v) : v;
}
console.log(res);
THIS
1 line of code
let result = Object.assign({}, info, otherInfo, {phone: [info.phone, otherInfo.phone]})
the Object.Assign is more faster

Javascript get array of objects from array of objects in array of objects

I have an array with registrations, inside this array is an array of students.
Now I want an array of all the students with only firstName, lastName and email.
registrations array
[
0: {
date: "2019-04-08T13:51:10.215Z"
onlyVAT: false,
students: [
0: {
email: "ben#test.be",
firstName: "Bennn",
lastName: "test",
phone: "0898989"
...
}
]
}
]
What I have so far:
this.registrations.map(
registration => registration.students.map(
student => { return {
firstName: student.firstName,
lastName: student.lastName,
email: student.email
}}
)
);
but this returns an array of arrays
0: [
0: {firstName: "Bennn", lastName: "test", email: "ben#test.be"},
1: ...
]
what I want is an array of (partial) student objects
[
0: {firstName: "Bennn", lastName: "test", email: "ben#test.be"},
1: ...
]
ofcourse I could just loop and push to a new array but that's not what I want
Use flat() or flatMap(). Example:
const newArr = registrations.map(
registration => registration.students.map(
student => { return {
firstName: student.firstName,
lastName: student.lastName,
email: student.email
}}
)
).flat();
console.log(newArr);
Just use flatMap.
this.registrations.flatMap(...);
Or use reduce:
this.registrations.map(...).reduce((a, c) => [...a, c], []);
Here is a solution with two Array.reduce() functions and Object.values(), which will ensure that the output will contain only unique emails (in the example input I have two identical emails ben4#test.be):
const registrations = [
{
date: '2019-04-08T13:51:10.215Z',
onlyVAT: false,
students: [
{
email: 'ben#test.be',
firstName: 'Bennn',
lastName: 'test',
phone: '0898989'
},
{
email: 'ben2#test.be',
firstName: 'Bennn2',
lastName: 'test2',
phone: '0898989'
}
]
},
{
date: '2019-05-08T13:51:10.215Z',
onlyVAT: false,
students: [
{
email: 'ben3#test.be',
firstName: 'Bennn3',
lastName: 'test3',
phone: '0898989'
},
{
email: 'ben4#test.be',
firstName: 'Bennn4',
lastName: 'test4',
phone: '0898989'
},
{
email: 'ben4#test.be',
firstName: 'Bennn4',
lastName: 'test4',
phone: '0898989'
}
]
}
];
const result = registrations.reduce((res, {students}) => ({
...res,
...students.reduce((res2, {email, firstName, lastName}) => ({
...res2,
[email]: {email, firstName, lastName}
}), {})
}), {});
console.log(Object.values(result));
The result is obtained in such form since students is a field inside an object in the array.
You could simply apply a combination of concat and ... spread operator on the result obtained from map to get the final array of students.
const studentsMapped = this.registrations.map(
registration => registration.students.map(
student => { return {
firstName: student.firstName,
lastName: student.lastName,
email: student.email
}}
)
);
const students = [].concat(...studentsMapped);

Convert array of objects with same property to one object with array values

let data = [
{firstName: 'John', lastName: 'Doe'},
{firstName: 'Mike', lastName: 'Smith'}
]
console.log(data)
I want to transform this into one object like this
obj = {firstName: ['John', 'Mike'], lastName: ['Doe', 'Smith']}
should I use reduce?
A generic solution with Array#reduce method.
let result = data.reduce((obj, o) => {
// get all keys of object
Object.keys(o)
// iterate over the keys
.forEach(k => {
// define property if not defined
obj[k] = obj[k] || [];
// push the value to the array
obj[k].push(o[k]);
})
// return object
return obj;
// set initial value as an object for result
}, {})
let data = [{
firstName: 'John',
lastName: 'Doe'
},
{
firstName: 'Mike',
lastName: 'Smith'
}
]
let result = data.reduce((obj, o) => {
Object.keys(o)
.forEach(k => {
obj[k] = obj[k] || [];
obj[k].push(o[k]);
})
return obj;
}, {})
console.log(result)
You can use reduce to create a new version of the object.
The reduce() method executes a reducer function (that you provide) on each member of the array resulting in a single output value.
With reduce, we first pass in a function that executes on each item and returns a new output value, then we pass a second parameter defining the initial structure of the single output value.
let data = [
{firstName: 'John', lastName: 'Doe'},
{firstName: 'Mike', lastName: 'Smith'}
]
// o = the current output value
// i = the current item in the array
let result = data.reduce((o, i) => {
// Add the first/last names to the corresponding array
o.firstName.push(i.firstName)
o.lastName.push(i.lastName)
// Return the new current output value
return o
}, { firstName: [], lastName: [] }) // Sets the initial output value
console.log(result)
let data = [
{firstName: 'John', lastName: 'Doe'},
{firstName: 'Mike', lastName: 'Smith'}
]
var firstName = [];var lastName = [];
data.forEach(function(item){
firstName.push(item.firstName);
lastName.push(item.lastName);
})
let obj = {};
obj.firstName = firstName;
obj.lastName = lastName;
let dataModified = [];
dataModified.push(obj);
console.log(dataModified);
You can also make the logic more generic, irrespective of the properties known
let data = [{
firstName: 'John',
lastName: 'Doe'
},
{
firstName: 'Mike',
lastName: 'Smith'
}
]
let result = data.reduce((o, i) => {
for (const key in i) {
if (!o[key]) {
o[key] = [];
}
o[key].push(i[key]);
}
return o
}, {})
console.log(result)
Another simple thing we can do is to call map two times, once on the first names, and once on the last names.
let data = [
{firstName: 'John', lastName: 'Doe'},
{firstName: 'Mike', lastName: 'Smith'}
]
let result = {
firstName: data.map(i => i.firstName),
lastName: data.map(i => i.lastName)
}
console.log(result)
Here's a single iteration, functional, non-mutating solution:
let data = [
{firstName: 'John', lastName: 'Doe'},
{firstName: 'Mike', lastName: 'Smith'}
]
let result = data.reduce((res, {firstName, lastName}) => ({
firstName: [firstName, ...res.firstName],
lastName: [lastName, ...res.lastName]
}), {firstName: [], lastName: []})
console.log(result)

lodash convert Object of Objects to array of objects including key in it

sorry about poor explanation on the title.
basically i want to know if there's better way or shorter code to do my job. i recently started using lodash library.
so,
i have an object of objects like following.
{
key1:{ firstname: john, lastname: doe},
key2:{ firstname: david, lastname: smith},
}
eventually i wanna make them as following array of objects.
[
{ID: key1, firstname: john, lastname: doe },
{ID: key2, firstname: david, lastname: smith}
]
and this is what i did.
const ArrayOfObjects = [];
_.each(ObjectsOfObjects, (value, key) => {
ArrayOfObjects.push({
UID: key,
...value,
});
})
Lodash's _.map() can iterate objects. The 2nd param passed to the iteratee function is the key:
const input = {
key1:{ firstname: 'john', lastname: 'doe'},
key2:{ firstname: 'david', lastname: 'smith'},
}
const result = _.map(input, (v, UID) => ({ UID, ...v }))
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.min.js"></script>
Use Object.entries and .map:
const input = {
key1:{ firstname: 'john', lastname: 'doe'},
key2:{ firstname: 'david', lastname: 'smith'},
}
const transformed = Object.entries(input).map(([key, obj]) => Object.assign(obj, { ID: key }));
console.log(transformed);

What is the most efficient way to copy some properties from an object in JavaScript?

Say, I have an object:
const user = {_id: 1234, firstName: 'John', lastName: 'Smith'}
I want to create another object without the _id key:
const newUser = {firstName: 'John', lastName: 'Smith'}
I am using this:
const newUser = Object.assign({}, {firstName: user.firstName, lastName: user.lastName})
Is there a better way to do this?
You can achieve it with a form of destructuring:
const user = { _id: 1234, firstName: 'John', lastName: 'Smith' };
const { _id, ...newUser } = user;
console.debug(newUser);
However, at the time of writing this answer, the spread (...) syntax is still at the ECMAScript proposal stage (stage 3), so it may not be universally available in practice. You may use it with a "transpilation" layer such as Babel.
Do it with Array#reduce method with Object.keys method.
const user = {
_id: 1234,
fistName: 'John',
lastName: 'Smith'
};
var res = Object.keys(user).reduce(function(obj, k) {
if (k != '_id') obj[k] = user[k];
return obj;
}, {});
console.log(res);
You are taking a shallow copy twice: once with the object literal, and again with Object.assign. So just use the first of the two:
const newUser = {firstName: user.firstName, lastName: user.lastName};
The most efficient would most likely be a regular loop
const user = {_id: 1234, fistName: 'John', lastName: 'Smith'};
let obj = {}, key;
for (key in user) {
if ( key !== '_id' ) obj[key] = user[key];
}
console.log(obj)
This tiny function will select specific keys to either copy or exclude from copying. exclude take precedence:
function copy(obj, include=[], exclude=[]) {
return Object.keys(obj).reduce((target, k) => {
if (exclude.length) {
if (exclude.indexOf(k) < 0) target[k] = obj[k];
} else if (include.indexOf(k) > -1) target[k] = obj[k];
return target;
}, {});
}
// let's test it
const user = {
_id: 1234,
firstName: 'John',
lastName: 'Smith'
};
// both will return the same result but have different uses.
console.log(
'include only firstName and lastName:\n',
copy(user, ['firstName', 'lastName'])
);
console.log(
'exclude _id:\n',
copy(user, null, ['_id'])
);
Go through the object keys, put the wanted property keys in an array and use the Array.prototype.includes() to copy only these into the new object.
const account = {
id: 123456,
firstname: "John",
lastname: "Doe",
login: "john123",
site_admin: false,
blog: "https://opensource.dancingbear/",
email: "john123#example.com",
bio: "John ❤️ Open Source",
created_at: "2001-01-01T01:30:18Z",
updated_at: "2020-02-16T21:09:14Z"
};
function selectSomeProperties(account) {
return Object.keys(account).reduce(function(obj, k) {
if (["id", "email", "created_at"].includes(k)) {
obj[k] = account[k];
}
return obj;
}, {});
}
const selectedProperties = selectSomeProperties(account);
console.log(JSON.stringify(selectedProperties))
The result:
{"id":123456,"email":"john123#example.com","created_at":"2001-01-01T01:30:18Z"}

Categories

Resources