Best way to replace item in object? - javascript

I will fetch this data, the data is always diffrent. Sometimes admin exist sometimes not.
What is the best way to remove all the values in admin and add new value, if admin key exist?
const apiFetched = [{
persons: {
firstName: "John",
lastName: "Doe",
},
admin: {
firstName: "Jeff",
lastName: "Pan",
}
}]
If admin key exist I would like to replace everything in admin and add these:
{ firstName: "Alan", lastName: "Jack" }
like this:
const apiFetched = [{
persons: {
firstName: "John",
lastName: "Doe",
},
admin: {
firstName: "Alan",
lastName: "Jack",
},
}];

iterate the array via forEach
for each item which features an own admin property ...
assign to this item's admin property/object another object like superUser which can feature equally named and/or additional properties ...
in the 1st case, key-value pairs will be replaced/overwritten,
in the 2nd case the admin object would aggregate/accumulate new entries.
const apiFetched = [{
persons: {
firstName: "John",
lastName: "Doe",
},
admin: {
firstName: "Jeff",
lastName: "Pan",
},
}];
const superUser = { firstName: "Alan", lastName: "Jack" };
apiFetched
.forEach(item => {
if (item.hasOwnProperty('admin')) {
Object.assign(item.admin, superUser);
}
});
console.log({ apiFetched });
.as-console-wrapper { min-height: 100%!important; top: 0; }

Here you go:
const apiFetched = [{
persons: {
firstName: "John",
lastName: "Doe",
},
admin: {
firstName: "Jeff",
lastName: "Pan",
}
}]
apiFetched.forEach(i => {
if (i.admin) {
i.admin = {
firstname: "Alan",
lastname: "Jack"
}
}
})
console.log(apiFetched)

Related

Create New Object key value pair base on array value

I need to generate csv for my client data but I need to include all headers came from my models.
The problem is some of my old client data has no existing fields. I want to create a new object with all the headers as a key and leave some empty string if a client has no data or no existing fields. Thanks for helping!
Here example of headers as key
let header = ["firstname", "lastname", "age", "gender", "address"];
Example for client info
let userInfo = [
{
firstname: "John",
lastname: "Doe",
age: "20",
gender: "male",
},
{
firstname: "Jane",
lastname: "Doe",
},
];
Expected Output
let userInfo = [
{
firstname: "John",
lastname: "Doe",
age: "20",
gender: "male",
address: "",
},
{
firstname: "Jane",
lastname: "Doe",
age: "",
gender: "",
address: "",
},
];
you can create an empty object with array.reduce
const emptyObj = header.reduce((acc, key) => {
acc[key] = "";
return acc;
}, {});
and use array.map on userInfo to return an object that concat the empty object with the one with value
let header = ["firstname", "lastname", "age", "gender", "address"];
let userInfo = [{
firstname: "John",
lastname: "Doe",
age: "20",
gender: "male",
},
{
firstname: "Jane",
lastname: "Doe",
},
];
const emptyObj = header.reduce((acc, key) => {
acc[key] = "";
return acc;
}, {});
const result = userInfo.map(user => {
return {
...emptyObj,
...user
};
})
console.log(result);

javascript function to get list of objects and return new key with new value in new array

for privacy I explain simple example . function that get personal list and return new key with new
value like below:
personalList = [{
firstName: "elena",
lastName: "zakharova"
},
{
firstName: "alex",
lastName: "farmanda"
},
{
firstName: "mike",
lastName: "kenan"
}]
output should be like this:
desiredList =[{fullname :'elena zakhrova'},{fullname :'alex farmanda'}, fullname : 'mike kenan']
tried some ways but unfortunately did not get answer
Any solutions would be appreciated.
You can use map
const personalList = [{
firstName: "elena",
lastName: "zakharova"
},
{
firstName: "alex",
lastName: "farmanda"
},
{
firstName: "mike",
lastName: "kenan"
}]
console.log(personalList.map(({firstName,lastName}) => ({fullName: `${firstName} ${lastName}`})))
Here's How I Would Solve This Using For Loop. You Can Also Use Maps Like How #R4ncid Has Explained
var desiredlist = []
var personalList = [{
firstName: "elena",
lastName: "zakharova"
},
{
firstName: "alex",
lastName: "farmanda"
},
{
firstName: "mike",
lastName: "kenan"
}]
for (i=0;i<personalList.length;i++){
desiredlist.push({"fullname":personalList[i].firstName + " " + personalList[i].lastName})}
console.log(desiredlist)

Get accessed to plucked object using javascript and lodash

I have an array of users in my javascript. For each user I am comparing if that user appears in another list.
var users = USERS.getUsers();
for (var i = 0; i < users.length; i++) {
var u = users[i];
if (util.pluck(myList.adminUsers, 'email').includes(u.email)) {
// How do I check the value of the plucked value for myList.adminUsers.locationId ?
u.status = "admin";
}
}
users is an array of user objects.
[{...}]
0:
id: "1"
email: "johndoe#gmail.com"
firstname: "John"
lastname: "Doe"
roleid: "1"
_proto__: Object
1:
id: "2"
email: "janedoe#gmail.com"
firstname: "Jane"
lastname: "Doe"
roleid: "1"
_proto__: Object
myList.adminUsers is also an array of user objects but also with locationId.
[{...}]
0:
id: "1"
email: "johndoe#gmail.com"
firstname: "John"
lastname: "Doe"
roleid: "1"
locationId: "123"
_proto__: Object
I need to compare another field in this check. So I need to see if the plucked object from myList.adminUsers has a field locationId that equals x, but I'm not sure how to do this?
How can I get access to the plucked object so I can check the value of locationId?
Use findWhere instead of pluck. You can give it an object containing all the properties you want to match.
if (util.findWhere(myList.adminUsers, {email: u.email, locationId: u.locationId})) {
u.status = "admin";
}
This should give you the list of admins that are found in the list of users and are in the location ID you provide as a value (I set it as a variable).
const users = [
{
id: "1",
email: "johndoe#gmail.com",
firstname: "John",
lastname: "Doe",
roleid: "1"
},
{
id: "2",
email: "janedoe#gmail.com",
firstname: "Jane",
lastname: "Doe",
roleid: "1"
}
];
const admins = [
{
id: "1",
email: "johndoe#gmail.com",
firstname: "John",
lastname: "Doe",
roleid: "1",
locationId: "123"
}
];
const locationIdToFind = '123';
const adminsWithLocation = _.intersectionWith(admins, users, (admin, user) => _.isEqual(admin.email, user.email) && _.isEqual(admin.locationId, locationIdToFind));
console.log(adminsWithLocation);
<script src="https://cdn.jsdelivr.net/npm/lodash#4.17.15/lodash.min.js"></script>

How to merge an array of objects keep only properties in the first array

I have a working function that merges two arrays of objects by property a1 and a1. The solution was based on answers to some similar questions, however my requirement is to keep only the properties in the original array a1.
How can I adjust this function to return an array of objects containing only the properties in the first array?
Here is a JS fiddle with example data. Note that the output is logged to the console. Also note that the solution must be in vanilla Javascript ES6.
https://jsfiddle.net/dba9r3sf/
const a1 = [
{
FirstName: "John",
LastName: "Doe",
Age: 33,
Username: "jdoe"
},
{
FirstName: "Mary",
LastName: "Bloom",
Age: 63,
Username: "mbloom"
},
{
FirstName: "Alex",
LastName: "Arias",
Age: 21,
Username: "aarias"
}
];
const a2 = [
{
FirstName: "Johnathan",
LastName: "Doe",
Age: 34,
Username: "jdoe",
Job: "Graphic Designer"
},
{
FirstName: "Mary-Anne",
LastName: "Bloom",
Age: 64,
Username: "mbloom",
Job: "Investor"
},
{
FirstName: "Alex",
LastName: "Arias",
Age: 22,
Username: "aarias",
Job: "Student"
}
];
/**
* Merge an array of objects by property
* #param {array} a1 array 1 destination to be merged into
* #param {array} a2 array 2 source to be merged, overwrites existing values in a1
* #param {string} prop name of property to match for merge
* TODO: Set properties that exist on a1 only otherwise ignore
*/
function mergeByProperty(a1, a2, prop) {
let merged = [];
for (let i = 0; i < a1.length; i++) {
merged.push({
...a1[i],
...(a2.find((itmInner) => itmInner[prop] === a1[i][prop]))
});
}
return merged;
}
let result = mergeByProperty(a1, a2, 'Username');
console.log(JSON.stringify(result));
// Output:
[{"FirstName":"Johnathan","LastName":"Doe","Age":34,"Username":"jdoe","Job":"Graphic Designer"},{"FirstName":"Mary-Anne","LastName":"Bloom","Age":64,"Username":"mbloom","Job":"Investor"},{"FirstName":"Alex","LastName":"Arias","Age":22,"Username":"aarias","Job":"Student"}]
// Desired output (no "Job" property because that does not exist in the first array of objects):
[{"FirstName":"Johnathan","LastName":"Doe","Age":34,"Username":"jdoe"},{"FirstName":"Mary-Anne","LastName":"Bloom","Age":64,"Username":"mbloom},{"FirstName":"Alex","LastName":"Arias","Age":22,"Username":"aarias"}]
You can take keys form first array and then select corresponding key/value pair form second array
const a1 = [{FirstName: "John",LastName: "Doe",Age: 33,Username: "jdoe"},{FirstName: "Mary",LastName: "Bloom",Age: 63,Username: "mbloom"},{FirstName: "Alex",LastName: "Arias",Age: 21,Username: "aarias"}];
const a2 = [{FirstName: "Johnathan",LastName: "Doe",Age: 34,Username: "jdoe",Job: "Graphic Designer"},{FirstName: "Mary-Anne",LastName: "Bloom",Age: 64,Username: "mbloom",Job: "Investor"},{FirstName: "Alex",LastName: "Arias",Age: 22,Username: "aarias",Job: "Student"}];
function mergeByProperty(a1, a2, prop) {
let merged = [];
for (let i = 0; i < a1.length; i++) {
let found = a2.find((itmInner) => itmInner[prop] === a1[i][prop])
if(found){
found = Object.keys(a1[0]).reduce((op,inp)=>{
op[inp] = found[inp]
return op
},{})
}
merged.push({
...a1[i],
...found
});
}
return merged;
}
let result = mergeByProperty(a1, a2, 'Username');
console.log((result));
You can create a username map from a2 then simply Array.map over the a1 array and merge with a custom merge function which does nothing more than Array.reduce over the keys of a1 and assigns the values from a2:
const a1 = [ { FirstName: "John", LastName: "Doe", Age: 33, Username: "jdoe" }, { FirstName: "Mary", LastName: "Bloom", Age: 63, Username: "mbloom" }, { FirstName: "Alex", LastName: "Arias", Age: 21, Username: "aarias" } ];
const a2 = [ { FirstName: "Johnathan", LastName: "Doe", Age: 34, Username: "jdoe", Job: "Graphic Designer" }, { FirstName: "Mary-Anne", LastName: "Bloom", Age: 64, Username: "mbloom", Job: "Investor" }, { FirstName: "Alex", LastName: "Arias", Age: 22, Username: "aarias", Job: "Student" } ];
let obj = a2.reduce((r,c) => (r[c.Username] = c, r), {}) // username map
let merge = (a, b, props) => props.reduce((r,c) => (r[c] = b[c], r), a)
let result = a1.map(x => merge(x, obj[x.Username], Object.keys(x)))
console.log(result)
You can do something like this:
const a1 = [
{
FirstName: "John",
LastName: "Doe",
Age: 33,
Username: "jdoe"
},
{
FirstName: "Mary",
LastName: "Bloom",
Age: 63,
Username: "mbloom"
},
{
FirstName: "Alex",
LastName: "Arias",
Age: 21,
Username: "aarias"
}
];
const a2 = [
{
FirstName: "Johnathan",
LastName: "Doe",
Age: 34,
Username: "jdoe",
Job: "Graphic Designer"
},
{
FirstName: "Mary-Anne",
LastName: "Bloom",
Age: 64,
Username: "mbloom",
Job: "Investor"
},
{
FirstName: "Alex",
LastName: "Arias",
Age: 22,
Username: "aarias",
Job: "Student"
}
];
const result = a1.map((obj1, index) => {
const obj2 = a2[index];
if (obj2) {
return Object.keys(obj1).reduce((acc, key) => {
acc[key] = obj2[key];
return acc;
}, {});
}
return obj1;
}, []);
console.log(result);

Difference of two javascript arrays of objects

I have two arrays like this:
owners: [
{
userID: "58c4d7ac",
username: "John.Doe",
firstName: "John",
lastName: "Doe",
email: "John.Doe#acme.com"
},
{
userID: "68c4d7ac",
username: "User2.Name2",
firstName: "User2",
lastName: "Name2",
email: "dh#acme.com"
}
]
users: [
{
userID: "58c4d7ac",
username: "John.Doe",
firstName: "John",
lastName: "Doe",
email: "John.Doe#acme.com"
},
{
userID: "68c4d7ac",
username: "User2.Name2",
firstName: "User2",
lastName: "Name2",
email: "dh#acme.com"
},
{
userID: "88c4d7ac",
username: "User3.Name3",
firstName: "User3",
lastName: "Name3",
email: "dh#acme.com"
}
]
I would like to get an array of users which contains only the elements which are not in the owners array.
I tried different approaches. Finally, I ended up with the solution:
const usersItems = users.map(user => {
// Check whether the user is already an owner
if (owners.findIndex(owner => owner.userID === user.userID) === -1) {
return owner
} else {
return null;
}
});
console.log(usersItems);
// Filter out all items which are null
const newUsersItems = usersItems.filter(user => {
if (user) return user;
});
console.log(usersItems);
To me, it doesn't' look like a clean solution. Is there a cleaner and easier way to do this? As a result, I would like to have:
newUsers: [
{
userID: "88c4d7ac",
username: "User3.Name3",
firstName: "User3",
lastName: "Name3",
email: "dh#acme.com"
}
]
You could get rid of your map and just use the filter, (that's exactly what filter is for) somthing like
const filtered = users.filter(user => {
// Check whether the user is already an owner
return owners.findIndex(owner => owner.userID === user.userID) === -1
});
would probably work
You can use combination of filter and some functions like this:
const owners = [
{
userID: "58c4d7ac",
username: "John.Doe",
firstName: "John",
lastName: "Doe",
email: "John.Doe#acme.com"
},
{
userID: "68c4d7ac",
username: "User2.Name2",
firstName: "User2",
lastName: "Name2",
email: "dh#acme.com"
}
];
const users = [
{
userID: "58c4d7ac",
username: "John.Doe",
firstName: "John",
lastName: "Doe",
email: "John.Doe#acme.com"
},
{
userID: "68c4d7ac",
username: "User2.Name2",
firstName: "User2",
lastName: "Name2",
email: "dh#acme.com"
},
{
userID: "88c4d7ac",
username: "User3.Name3",
firstName: "User3",
lastName: "Name3",
email: "dh#acme.com"
}
];
const result = users.filter(user => !owners.some(owner => owner.userID === user.userID));
console.log(result);
First you can create a Set() with the userID's of the owners array, and then you can use Array.filter() on the users array to filter the users whose userID does not belong to the previous created set.
const owners = [
{userID: "58c4d7ac", username: "John.Doe", firstName: "John", lastName: "Doe", email: "John.Doe#acme.com"},
{userID: "68c4d7ac", username: "User2.Name2", firstName: "User2", lastName: "Name2", email: "dh#acme.com"}
];
const users = [
{userID: "58c4d7ac", username: "John.Doe", firstName: "John", lastName: "Doe", email: "John.Doe#acme.com"},
{userID: "68c4d7ac", username: "User2.Name2", firstName: "User2", lastName: "Name2", email: "dh#acme.com"},
{userID: "88c4d7ac", username: "User3.Name3", firstName: "User3", lastName: "Name3", email: "dh#acme.com"}
];
let ownerIdsSet = new Set(owners.map(x => x.userID));
let res = users.filter(x => !ownerIdsSet.has(x.userID));
console.log(res);
.as-console {background-color:black !important; color:lime;}
But why to construct a Set first?
In summary, it will improve the performance of the filtering process, particularly if the owners array is large. You should note that methods like findIndex(), find() and some() needs to traverse the array for check to the related condition while checking if the userID belongs to the Set is a O(1) calculation. However, of course, there will be an extra overload at initialization to create the mentioned Set.
You can use filter and some
const owners = [{userID:"58c4d7ac",username:"John.Doe",firstName:"John",lastName:"Doe",email:"John.Doe#acme.com"},{userID:"68c4d7ac",username:"User2.Name2",firstName:"User2",lastName:"Name2",email:"dh#acme.com"}]
const users = [{userID:"58c4d7ac",username:"John.Doe",firstName:"John",lastName:"Doe",email:"John.Doe#acme.com"},{userID:"68c4d7ac",username:"User2.Name2",firstName:"User2",lastName:"Name2",email:"dh#acme.com"},{userID:"88c4d7ac",username:"User3.Name3",firstName:"User3",lastName:"Name3",email:"dh#acme.com"}]
const newUsers = users
.filter(({userID}) => !owners.some(({userID:ownerID})=> ownerID === userID))
console.log(newUsers)
You can just use a single .filter() function, like so:
let owners = [{userID: "58c4d7ac",username: "John.Doe",firstName: "John",lastName: "Doe",email: "John.Doe#acme.com"},{userID: "68c4d7ac",username: "User2.Name2",firstName: "User2",lastName: "Name2",email: "dh#acme.com"}];
let users = [{userID: "58c4d7ac",username: "John.Doe",firstName: "John",lastName: "Doe",email: "John.Doe#acme.com"},{userID: "68c4d7ac",username: "User2.Name2",firstName: "User2",lastName: "Name2",email: "dh#acme.com"},{userID: "88c4d7ac",username: "User3.Name3",firstName: "User3",lastName: "Name3",email: "dh#acme.com"}];
let newUsersItems = users.filter(user => owners.findIndex(owner => owner.userID === user.userID) === -1);
console.log(newUsersItems)
You can just use a single .filter() function, like so:
You can use the reduce function
const diff = users.reduce((acc, user) => {
if(!owners.find(owner => owner.id === user.id){
acc.push(user);
}
return acc;
}, []);
to avoid use the find() function every loop you can store owner ids in a array with the map an just use includes()
const ownersIds = owners.map(owner => owner.id);
const diff = users.reduce((acc, user) => {
if(!ownersIds.includes(user.id){
acc.push(user);
}
return acc;
}, []);
You can use the function some or find, this approach uses the function find
let owners = [ { userID: "58c4d7ac", username: "John.Doe", firstName: "John", lastName: "Doe", email: "John.Doe#acme.com" }, { userID: "68c4d7ac", username: "User2.Name2", firstName: "User2", lastName: "Name2", email: "dh#acme.com" } ],
users = [ { userID: "58c4d7ac", username: "John.Doe", firstName: "John", lastName: "Doe", email: "John.Doe#acme.com" }, { userID: "68c4d7ac", username: "User2.Name2", firstName: "User2", lastName: "Name2", email: "dh#acme.com" }, { userID: "88c4d7ac", username: "User3.Name3", firstName: "User3", lastName: "Name3", email: "dh#acme.com" } ],
result = users.filter(({userID}) => !owners.find(o => o.userID === userID));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Categories

Resources