So I have an array of objects with many, keys, something like that:
[
{ id: 1,
phoneNumber: 12345,
name: "John",
underLicense: true
},
{ id: 2,
phoneNumber: 12345,
name: "Jane",
underLicense: false
}
]
The way i want it to look like is this:
[
{ listPhone: [
{ number: 12345,
underLicense: true
},
{ number: 12345
underLicense: false
}
]
}
]
so for that, first i do the map(), and then I push it into listPhones
here is my function
saveLicense() {
const listPhone = this.toSend.map(x => {
return {
number: x.phoneNumber,
underLicense: x.underLicense
};
});
const savedPhones = [];
savedPhones.push({listPhone: listPhone});
}
The question is, is there a way to to it in the map() metod, without having to use push in the second step
You could directly map to an expression for a property value.
saveLicense() {
const
savedPhones = [{ listPhone: this.toSend.map(({ phoneNumber: number, underLicense }) =>
({ number, underLicense })
) }];
}
Maybe:
saveLicense () {
const listPhone = this.toSend.map((x) => ({
number: x.phoneNumber,
underLicense: x.underLicense,
}));
const savedPhones = [{ listPhone }];
};
saveLicense() {
const listPhone = this.toSend.map(x => {
return { listPhone: {
number: x.phoneNumber,
underLicense: x.underLicense
}
};
});
return [listPhone]
}
Related
I have an array
const dataCheck = ["Rohit","Ravi"];
I have another array of object
const userData = [
{ name: "Sagar" },
{ name: "Vishal" },
{ name: "Rohit" },
{ name: "Ravi" },
];
I want to check if any value in dataCheck is present in the userData and then return a new array with the below data
const newData = [
{ name: "Sagar" },
{ name: "Vishal" },
{ name: "Rohit", status: "present" },
{ name: "Ravi", status: "present" },
];
I tried to do something using loops but not getting the expected results
const dataCheck = ["Rohit", "Ravi"];
const userData = [
{ name: "Sagar" },
{ name: "Vishal" },
{ name: "Rohit" },
{ name: "Ravi" }
];
let newDataValue = {};
let newData = [];
userData.forEach((user) => {
const name = user.name;
dataCheck.forEach((userName) => {
if (name === userName) {
newDataValue = {
name: name,
status: "present"
};
} else {
newDataValue = {
name: name
};
}
newData.push(newDataValue);
});
});
console.log(newData);
My trial gives me repeated results multiple results which is just duplicates
You should use map() and a Set.
const dataCheck = ["Rohit","Ravi"];
const userData = [
{ name: "Sagar" },
{ name: "Vishal" },
{ name: "Rohit" },
{ name: "Ravi" },
];
const set = new Set(dataCheck);
const output = userData.map(data => set.has(data.name) ? ({...data, status: "present"}): data)
console.log(output)
.as-console-wrapper { max-height: 100% !important; top: 0; }
A Set allows for lookups in O(1) time and therefore this algorithm works in O(n) time. If you would use the array for lookups (e.g. using indcludes(), find() etc.) the runtime would be O(n²). Although this will certainly not matter at all for such small arrays, it will become more relevant the larger the array gets.
map() is used here because you want a 1:1 mapping of inputs to outputs. The only thing to determine then is, what the output should be. It is either the input, if the value is not in the Set, or it is the input extended by one property status set to "present". You can check for the presence in a Set using the has() method and can use the ternary operator ? to make the decision which case it is.
const dataCheck = ["Rohit", "Ravi"];
const userData = [
{ name: "Sagar" },
{ name: "Vishal" },
{ name: "Rohit" },
{ name: "Ravi" },
];
// map through every object and check if name property
// exists in data check with help of filter.
// if it exists the length of filter should be 1 so
// you should return { name: el.name, status: "present" } else
// return { name: el.name }
let newData = userData.map((el) => {
if (dataCheck.filter((name) => name === el.name).length > 0) {
return { name: el.name, status: "present" };
} else {
return { name: el.name };
}
});
console.log("newdata: ", newData);
A better approach would be to use map over userData array, find for matching element in dataCheck, if found return matching element + a status key or just return the found element as it is.
const dataCheck = ["Rohit","Ravi"];
const userData = [
{ name: "Sagar" },
{ name: "Vishal" },
{ name: "Rohit" },
{ name: "Ravi" },
];
const getUpdatedObject = () => {
return userData.map(userData => {
const userDetail = dataCheck.find(data => userData.name === data);
if(userDetail) return {userDetail, status:"present"}
else return {...userData}
});
}
console.log(getUpdatedObject())
Working fiddle
Loop through userData, check if name is includes in dataCheck. If true add status 'present'.
const dataCheck = ["Rohit","Ravi"];
const userData = [
{ name: "Sagar" },
{ name: "Vishal" },
{ name: "Rohit" },
{ name: "Ravi" },
];
for (let user of userData) {
if(dataCheck.includes(user.name)) {
user.status = 'present'
}
}
console.log(userData)
You are seeing repeated results due to the second loop dataCheck.forEach((userName) => { as every loop of dataCheck will fire the if/else statement and add something to the final array. However many values you add to dataCheck will be however many duplicates you get.
Only need to loop through one array and check if the value is in the other array so no duplicates get added.
const dataCheck = ["Rohit", "Ravi"];
const userData = [{ name: "Sagar" }, { name: "Vishal" }, { name: "Rohit" }, { name: "Ravi" }];
let newDataValue = {};
let newData = [];
// loop thru the users
userData.forEach((user) => {
// set the user
const name = user.name;
// check if in array
if (dataCheck.indexOf(name) >= 0) {
newDataValue = {
name: name,
status: "present",
};
}
// not in array
else {
newDataValue = {
name: name,
};
}
newData.push(newDataValue);
});
console.log(newData);
So you will do like this :
const dataCheck = ["Rohit","Ravi"];
const userData = [
{ name: "Sagar" },
{ name: "Vishal" },
{ name: "Rohit" },
{ name: "Ravi" },
];
const newUserData = userData.map( user => {
dataCheck.forEach( data => {
if( data === user.name )
user.status = "present";
});
return user;
} );
console.log( newUserData );
Tying to change key values inside an object but its adding double values or its adding all values at once. Every name must get an value which in this case is a language slug. Not sure what I am doing wrong.
// the data
const routesObj = [
{ name: 'dashboard.index' },
{ name: 'settings.index' },
{ name: 'settings.general' },
{ ... }
]
// end results (how i want it to be)
[
{
nl: {
routes: [
{
name: 'nl.dashboard.index'
},
{
name: 'nl.dashboard.index'
},
{
name: 'nl.settings.general'
}
]
}
},
{
en: {
routes: [
{
name: 'en.dashboard.index'
},
{
name: 'en.dashboard.index'
},
{
name: 'en.settings.general'
}
]
}
}
]
// how its working now(not good)
[
{
nl: {
routes: [
{
name: 'en.nl.dashboard.index'//adding both languages
},
...
]
}
},
...
]
const routeBuilder = (routes, languages) => {
let newRoutes = []
languages.forEach(function(lang){
Object.keys(routes).forEach(function(key){
routes[key]['name'] = lang+'.'+routes[key]['name']
});
newRoutes[lang] = {routes};
});
return newRoutes
}
routeBuilder(routesObj, ['nl','en'])
The problem is here:
Object.keys(routes).forEach(function(key){
routes[key]['name'] = lang+'.'+routes[key]['name']
});
newRoutes[lang] = {routes};
routes is a reference to routesObj, so the code above modifies the original object in each languages.forEach iteration. The solution is to clone routes so that each iteration has a unique copy.
newRoutes is an array, but it's being used like an object in newRoutes[lang]. To insert an object into the newRoutes array, use Array.prototype.push.
const routesObj = [
{ name: 'dashboard.index' },
{ name: 'settings.index' },
{ name: 'settings.general' },
]
const routeBuilder = (routes, languages) => {
const newRoutes = []
languages.forEach(function(lang) {
routes = routesObj.map(x => ({...x})); // 1️⃣
Object.keys(routes).forEach(function(key){
routes[key]['name'] = lang+'.'+routes[key]['name']
});
newRoutes.push({ [lang]: { routes } }); // 2️⃣
})
return newRoutes;
}
const routes = routeBuilder(routesObj, ['nl','en'])
console.log(routes)
Alternatively, use nested Array.prototoype.maps:
const routesObj = [
{ name: 'dashboard.index' },
{ name: 'settings.index' },
{ name: 'settings.general' },
]
const routeBuilder = (routes, languages) => {
return languages.map(lang => {
return {
[lang]: {
routes: routes.map(route => ({ ...route, name: lang + '.' + route.name })),
}
}
})
}
const routes = routeBuilder(routesObj, ['nl','en'])
console.log(routes)
I have two arrays of objects.
const details = [
{
ciphertext: 1234,
buyer: {
op_timezone: 7689,
op_city: 'Name1',
},
assignment_info: {
info: {
end_data: 1456,
start_date: 2389,
}
}
},
{
ciphertext: 5678,
buyer: {
op_timezone: 4568,
op_city: 'Name2',
},
assignment_info: {
info: {
end_data: 3467,
start_date: 8753,
}
}
},
];
const jobIds = [
{
id: 1,
},
{
id: 2,
},
];
I need to combine two arrays and take the assignment_info.info and buyer fields from each object.
function getDetailsBuyersWithJobIds(jobIds, details) {
return jobIds.map((item, index) => ({
...item,
...details[index].buyer,
}));
};
function getDetailsAssignmentInfosWithJobIds(jobIds, details) {
return jobIds.map((item, index) => ({
...item,
...details[index].assignment_info.info,
}));
};
The question is, how can two functions be combined into one?
That there would be no duplicate function, since they perform the same thing.
You can do a generic mapping function and pass it a getter function that will be able to fetch the proper data, not sure it will help the global readibility though.
What do you think about that?
const genericMapper = (getter) => (item, index) => ({
...item,
...getter(details[index]),
});
function getDetailsBuyersWithJobIds(jobIds, details) {
return jobIds.map(genericMapper(it => it.buyer));
};
function getDetailsAssignmentInfosWithJobIds(jobIds, details) {
return jobIds.map(genericMapper(it => it.assignment_info.info));
};
const details = [
{
ciphertext: 1234,
buyer: {
op_timezone: 7689,
op_city: 'Name1',
},
assignment_info: {
info: {
end_data: 1456,
start_date: 2389,
}
}
},
{
ciphertext: 5678,
buyer: {
op_timezone: 4568,
op_city: 'Name2',
},
assignment_info: {
info: {
end_data: 3467,
start_date: 8753,
}
}
},
];
const jobIds = [
{
id: 1,
},
{
id: 2,
},
];
console.log(getDetailsBuyersWithJobIds(jobIds, details));
console.log(getDetailsAssignmentInfosWithJobIds(jobIds, details));
You can add values on return object based on condition something like this
const details = [{ciphertext: 1234,buyer: {op_timezone: 7689,op_city: 'Name1',},assignment_info: {info: {end_data: 1456,start_date: 2389,}}},{ciphertext: 5678,buyer: {op_timezone: 4568,op_city: 'Name2',},assignment_info: {info: {end_data: 3467,start_date: 8753,}}},];
const jobIds = [{id: 1,},{id: 2,},];
function getDetails(jobIds, details, props = {
getBuyer: true
}) {
return jobIds.map((item, index) => ({
...item,
...(props.getBuyer && { ...details[index].buyer
}),
...(props.getAssignment && { ...details[index].assignment_info.info
})
}));
};
console.log(getDetails([1], details, {
getBuyer: true
}))
console.log(getDetails([1], details, {
getAssignment: true
}))
Here props = { getBuyer: true} used to set a default value.
The array
const users = dedup([
{ id: 1, email: 'foo#example.com' },
{ id: 2, email: 'sho#example.com' },
{ id: 1, email: 'bin#example.com' },
]);
/* would ideally like it to return
Object {
email: "foo#example.com",
email: "bin#example.com",
id:1
}, Object {
email: "sho#example.com",
id:2
} */
The Hash Table
function dedup(arr) {
var hashTable = {};
return arr.filter(function (el) {
var key = JSON.stringify(el);
var match = Boolean(hashTable[key]);
return (match ? false : hashTable[key] = true);
});
}
My returns statement that only filters out exact duplicates and doesn't join similar id's with different email addresses
console.log(users);
/* currently returns
Object {
email: "foo#example.com",
id:1
}, Object {
email: "sho#example.com",
id:2
},
{ id: 1, email: 'bin#example.com' },
]); */
function dedup(arr) {
var hashTable = {};
arr.forEach(function(el) {
if (!hashTable.hasOwnProperty(el.id)) {
hashTable[el.id] = [];
}
hashTable[el.id].push(el.email);
});
return hashTable;
}
Result should be:
{
1: ['bin#example.com', 'foo#example.com' ],
2: ['sho#example.com']
}
Hope this helped.
I need to split an Array by its objects subvalue (type).
Let's assume I have following array:
[
{id:1,name:"John",information: { type :"employee"}},
{id:2,name:"Charles",information: { type :"employee"}},
{id:3,name:"Emma",information: { type :"ceo"}},
{id:4,name:"Jane",information: { type :"customer"}}
]
and I want to split the object by information.type so my final result looks like:
[
{
type:"employee",
persons:
[
{id:1,name:"John",information: { ... }},
{id:2,name:"Charles",information: { ... }
]
},
{
type:"ceo",
persons:
[
{id:3,name:"Emma",information: { ... }}
]
},
{
type:"customer",
persons:
[
{id:4,name:"Jane",information: { ... }}
]
},
]
Underscore is available at my Project. Any other helper library could be included.
Of course I could loop through the array and implement my own logic, but i was looking for cleaner solution.
This returns exactly what you want:
_.pairs(_.groupBy(originalArray, v => v.information.type)).map(p => ({type: p[0], persons: p[1]}))
A solution in plain Javascript with a temporary object for the groups.
var array = [{ id: 1, name: "John", information: { type: "employee" } }, { id: 2, name: "Charles", information: { type: "employee" } }, { id: 3, name: "Emma", information: { type: "ceo" } }, { id: 4, name: "Jane", information: { type: "customer" } }],
result = [];
array.forEach(function (a) {
var type = a.information.type;
if (!this[type]) {
this[type] = { type: type, persons: [] };
result.push(this[type]);
}
this[type].persons.push({ id: a.id, name: a.name });
}, {});
document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');
You could use the groupBy function of underscore.js:
var empList = [
{id:1,name:"John",information: { type :"employee"}},
{id:2,name:"Charles",information: { type :"employee"}},
{id:3,name:"Emma",information: { type :"ceo"}},
{id:4,name:"Jane",information: { type :"customer"}}
];
_.groupBy(empList, function(emp){ return emp.information.type; });