I have an array of objects(Vue 3 prop) like below. The array is for room objects. Each room contains adults and childs array with adult and child objects. Now I need to mark the duplicate names (first and last name together) by adding a property name error (Shown in example).
[
{
"RoomType":{ },
"Price": { },
"Messages": [],
"CancellationPolicyStatus": "",
"adults": [
{ "title": "Mr.", "first": "John", "last": "Doe"},
{ "title": "Mrs.", "first": "Jane", "last": "Doe"}
],
"children": [
{ "title": "Ms.", "first": "Jane", "last": "Doe"},
{ "title": "Mr.", "first": "Joe", "last": "Doe" }
]
},
{
"RoomType":{ },
"Price": { },
"Messages": [],
"CancellationPolicyStatus": "",
"adults": [
{ "title": "Mr.", "first": "Johny", "last": "Doe",},
{ "title": "Mrs.", "first": "Jane", "last": "Doe",}
],
"children": [
{ "title": "Ms.", "first": "Jane", "last": "Doe"},
{ "title": "Mr.", "first": "Jui", "last": "Doe"}
]
},
]
After I run the function or code in question. The resulting array should look like below.
[
{
"RoomType":{ },
"Price": { },
"Messages": [],
"CancellationPolicyStatus": "",
"adults": [
{ "title": "Mr.", "first": "John", "last": "Doe"},
{ "title": "Mrs.", "first": "Jane", "last": "Doe", "error": "Duplicate name, please update." }
],
"children": [
{ "title": "Ms.", "first": "Jane", "last": "Doe", "error": "Duplicate name, please update." },
{ "title": "Mr.", "first": "Joe", "last": "Doe" }
]
},
{
"RoomType":{ },
"Price": { },
"Messages": [],
"CancellationPolicyStatus": "",
"adults": [
{ "title": "Mr.", "first": "Johny", "last": "Doe", },
{ "title": "Mrs.", "first": "Jane", "last": "Doe", "error": "Duplicate name, please update." }
],
"children": [
{ "title": "Ms.", "first": "Jane", "last": "Doe", "error": "Duplicate name, please update." },
{ "title": "Mr.", "first": "Jui", "last": "Doe" }
]
},
]
Update:
This is my first question to Stack Overflow, even though I am regular user of the platform for last 7+ years.
I am overwhelmed by the responses and definitely will go through each solution.
I am not a JS developer and tried to make a solution (inspired by
vanowm's comment) that now looks like below. I believe the responses have a better solution.
const isDuplicate = function (names, person) {
let result = false;
names.forEach(function (name) {
if(name.first === person.first && name.last === person.last){
result = true;
}
});
return result;
}
const validateNames = function () {
let names = [];
rooms.forEach(function (room) {
room.adults.forEach(function (adult) {
if (isDuplicate(names, adult)) {
adult.error = 'Duplicate name, please update.'
// I can do this because it is a Vue Reactive.
} else {
adult.error = ''
names.push(adult);
}
})
room.childs.forEach(function (child) {
if (isDuplicate(names, child)) {
child.error = 'Duplicate name, please update.'
} else {
child.error = ''
names.push(child);
}
})
});
};```
Here's my naive attempt
I assumed you want to find duplicates among adults separately from duplicates among children - it's not clear since the only duplicate is Jane Doe and she appears twice as an adult and twice as a child!
const data = [
{
RoomType: {},
Price: {},
Messages: [],
CancellationPolicyStatus: "",
adults: [
{ title: "Mr.", first: "John", last: "Doe" },
{ title: "Mrs.", first: "Jane", last: "Doe" },
],
childs: [
{ title: "Ms.", first: "Jane", last: "Doe" },
{ title: "Mr.", first: "Joe", last: "Doe" },
],
},
{
RoomType: {},
Price: {},
Messages: [],
CancellationPolicyStatus: "",
adults: [
{ title: "Mr.", first: "Johny", last: "Doe" },
{ title: "Mrs.", first: "Jane", last: "Doe" },
],
childs: [
{ title: "Ms.", first: "Jane", last: "Doe" },
{ title: "Mr.", first: "Jui", last: "Doe" },
],
},
];
const store = {};
const findDupe = (o, type) => {
const key = [o.first, o.last].join();
const tbl = (store[type] = store[type] || {});
if (!tbl[key]) {
tbl[key] = [o];
return;
}
if (tbl[key].length === 1) {
tbl[key][0].error = "Duplicate name, please update.";
}
o.error = "Duplicate name, please update.";
tbl[key].push(o);
};
data.forEach((record) => {
record.adults.forEach((adult) => findDupe(adult, "adults"));
record.childs.forEach((child) => findDupe(child, "childs"));
});
console.log(JSON.stringify(data, null, 4));
Edit: as requested - explanation of findDupe -
creates a "key" by combining first and lastname together
creates store[type] object if it doesn't exist
if the key made in 1 doesn't exist in the object made in 2, create the key as an array and store the current person in it - done
otherwise it's a duplicate - add it to the array in step 3
if it's the first duplicate, mark the first person in the array as a duplicate
mark this person as a duplicate
Create two objects (database) where first and last names will be stored, iterate your objects and check if first/last name exists in the database, if not, add them to the database:
const arr = [
{
"RoomType":{ },
"Price": { },
"Messages": [],
"CancellationPolicyStatus": "",
"adults": [
{ "title": "Mr.", "first": "John", "last": "Doe"},
{ "title": "Mrs.", "first": "Jane", "last": "Doe"}
],
"childs": [
{ "title": "Ms.", "first": "Jane", "last": "Doe"},
{ "title": "Mr.", "first": "Joe", "last": "Doe" }
]
},
{
"RoomType":{ },
"Price": { },
"Messages": [],
"CancellationPolicyStatus": "",
"adults": [
{ "title": "Mr.", "first": "Johny", "last": "Doe",},
{ "title": "Mrs.", "first": "Jane", "last": "Doe",}
],
"childs": [
{ "title": "Ms.", "first": "Jane", "last": "Doe"},
{ "title": "Mr.", "first": "Jui", "last": "Doe"}
]
},
];
function check(arr)
{
//we'll store names for both adults and children in these objects
const first = {},
last = {};
return arr.map(room =>
{
const checkDup = person =>
{
//check if this first/last name already exists in our database
if (first[person.first] !== undefined && last[person.last] !== undefined)
{
//set error property in current person object
person.error = "Duplicate name, please update.";
//set error property in the original person object
first[person.first].error = person.error;
}
else
{
//store names in the database
first[person.first] = person;
last[person.last] = person;
}
return person;
}
room.adults.forEach(checkDup);
room.childs.forEach(checkDup);
return room;
});
}
console.log(check(arr));
/*
[
{
"RoomType":{ },
"Price": { },
"Messages": [],
"CancellationPolicyStatus": "",
"adults": [
{ "title": "Mr.", "first": "John", "last": "Doe"},
{ "title": "Mrs.", "first": "Jane", "last": "Doe", "error": "Duplicate name, please update." }
],
"childs": [
{ "title": "Ms.", "first": "Jane", "last": "Doe", "error": "Duplicate name, please update." },
{ "title": "Mr.", "first": "Joe", "last": "Doe" }
]
},
{
"RoomType":{ },
"Price": { },
"Messages": [],
"CancellationPolicyStatus": "",
"adults": [
{ "title": "Mr.", "first": "Johny", "last": "Doe", },
{ "title": "Mrs.", "first": "Jane", "last": "Doe", "error": "Duplicate name, please update." }
],
"childs": [
{ "title": "Ms.", "first": "Jane", "last": "Doe", "error": "Duplicate name, please update." },
{ "title": "Mr.", "first": "Jui", "last": "Doe" }
]
},
]
*/
not to be a grammar nazzy, but it's children, not childs
There are probably better ways to do this, but this should suit your needs.
You'll need to loop over both of the arrays checking the names of each object.
Set the error for both adult and child if you come across a match.
Should also be worth noting that your parent array of these objects was not named (unless it is named props, I don't use Vue so I don't know if that is a convention or not) so you would have to loop through every object in the parent array to do this.
const namesArray = [];
// Loop over the adults array. Store the names and index to check against later
adults.forEach((adult, index) => {
let fullName = adult.first + adult.last;
namesArray.push({name: fullName, index: index});
}
// Loop over the child array
// If the name of a child is found in the namesArray, set the error for the child and the corresponding adult
children.forEach(child => {
let fullName = child.first + child.last;
namesArray.forEach(nameObject => {
if(nameObject.name === fullName) {
child.error = 'Duplicate name, please update.';
adults[nameObject.index].error = 'Duplicate name, please update.';
}
}
}
[
{
"_id": "5edfb4e587a1873120735dcf",
"firstname": "abc",
"lastname": "abc",
"sessions": [
{
"_id": "5efc68d146d8330a449e7108",
"sessionID": null
},
{
"_id": "5efc68e646d8330a449e710a",
"sessionID": null
}
]
},
{
"_id": "5eedf5685bdb7d33c83186e7",
"firstname": "sam",
"lastname": "ple",
"sessions": [
{
"_id": "5efc692d46d8330a449e710c",
"sessionID": null
}
]
},
{
"_id": "5ef04df83e41dd5b78fe6908",
"firstname": "User",
"lastname": "name1",
"sessions": [
{
"_id": "5efc6a8846d8330a449e710e",
"sessionID": null
},
{
"_id": "5efc6abd46d8330a449e7110",
"sessionID": null
}
]
},
{
"_id": "5efe0d0c7300073244d765d9",
"sessions": [],
"firstname": "User",
"lastname": "name1"
}
]
You need to map over your array and filter out sessions with null
let originalArray = [
{
"_id": "5edfb4e587a1873120735dcf",
"firstname": "abc",
"lastname": "abc",
"sessions": [
{
"_id": "5efc68d146d8330a449e7108",
"sessionID": null
},
{
"_id": "5efc68e646d8330a449e710a",
"sessionID": null
}
]
},
.... the rest of your orignal object
]
let newArray = originalArray.map(item => {
let sessions = item.sessions.filter(session => {
return session.sessionID !== null
})
return {
...item,
sessions
}
})
Im trying to filter and take only the contacts that the number is in numbers my problem is that one numbers could be the secondary number of the contact and filter(indexOf(foreach())) doesn't seem to work here any advice?
const filteredContacts = contacts.filter(contact => numbers.indexOf(contact.phoneNumbers.forEach(phone => phone.number)) > -1);
//sample of contacts
Object {
"company": "Financial Services Inc.",
"contactType": "person",
"firstName": "Hank",
"id": "2E73EE73-C03F-4D5F-B1E8-44E85A70F170",
"imageAvailable": false,
"jobTitle": "Portfolio Manager",
"lastName": "Zakroff",
"middleName": "M.",
"name": "Hank M. Zakroff",
"phoneNumbers": Array [
Object {
"countryCode": "us",
"digits": "5557664823",
"id": "337A78CC-C90A-46AF-8D4B-6CC43251AD1A",
"label": "work",
"number": "(555) 766-4823",
},
Object {
"countryCode": "us",
"digits": "7075551854",
"id": "E998F7A3-CC3C-4CF1-BC21-A53682BC7C7A",
"label": "other",
"number": "(707) 555-1854",
},
],
},
Object {
"contactType": "person",
"firstName": "David",
"id": "E94CD15C-7964-4A9B-8AC4-10D7CFB791FD",
"imageAvailable": false,
"lastName": "Taylor",
"name": "David Taylor",
"phoneNumbers": Array [
Object {
"countryCode": "us",
"digits": "5556106679",
"id": "FE064E55-C246-45F0-9C48-822BF65B943F",
"label": "home",
"number": "555-610-6679",
},
],
},
]
//Sample of numbers
numbers = [
(707) 555-1854,
555-610-6679
]
//Expected
filteredContacts = //Both contacts
This should work for you:
const contacts= [
{
company: "Financial Services Inc.",
// ....
phoneNumbers:[
{
//...
number: "(555) 766-4823",
},
{
//...
number: "555-610-6679",
}
]
}
//...
];
//Sample of numbers
const numbers = [
'(707) 555-1854',
'555-610-6679'
]
const filteredContacts = contacts.filter(contact => {
let number_exists=false;
contact.phoneNumbers.map(phone => phone.number).forEach( phoneNr =>{
if(numbers.indexOf(phoneNr)>-1) number_exists=true;
}
);
return number_exists;
}
);
//Expected
console.log(filteredContacts)
My data:
{
"rows": [
{
"id": 3,
"code": "airtel121",
"position": "manager",
"salary": "25000",
"login": {
"id": 4,
"username": "sameer",
"firstName": "Mohamed",
"lastName": "Sameer",
"code": "airtel121",
}
},
{
"id": 7,
"code": "airtel121",
"position": null,
"salary": null,
"login": {
"id": 8,
"username": "annamalai",
"firstName": "Anna",
"lastName": "malai",
"code": "airtel121",
}
}
]
}
My expected outcome:
{
"rows": [
{
"id": 4,
"username": "sameer",
"firstName": "Mohamed",
"lastName": "Sameer",
"code": "airtel121",
"staffs": [
{
"id": 3,
"code": "airtel121",
"position": "manager",
"salary": "25000",
}
]
},
{
"id": 8,
"username": "annamalai",
"firstName": "Anna",
"lastName": "malai",
"code": "airtel121",
"staffs": [
{
"id": 7,
"code": "airtel121",
"position": null",
"salary": null",
}
]
}
]
}
I tried, but only i am getting first object, check my fiddle:
http://jsbin.com/qaqehakuwi/edit?js,output
Is this possible to loop using for loop or it can be done by lodash?
Check my above jsbin link for code.
I am using ES6 way of code in my project, so i used spread operator.
You can use map to create the rows array of the new object from the rows array of the old one:
let newObj = {
rows: oldObj.rows.map(row => { // map the rows of the old object into the rows of the new object
let { login, ...rest } = row; // for each object/row get the login object as 'login' and the rest of the props as 'rest'
return { ...login, staffs: [rest] }; // return a new object that has the props of 'login' and an additional prop 'staffs' which is an array containing 'rest'
})
};
Example:
let oldObj = {"rows":[{"id":3,"code":"airtel121","position":"manager","salary":"25000","login":{"id":4,"username":"sameer","firstName":"Mohamed","lastName":"Sameer","code":"airtel121"}},{"id":7,"code":"airtel121","position":null,"salary":null,"login":{"id":8,"username":"annamalai","firstName":"Anna","lastName":"malai","code":"airtel121"}}]};
let newObj = {
rows: oldObj.rows.map(row => {
let { login, ...rest } = row;
return { ...login, staffs: [rest] };
})
};
console.log(newObj);
I have the following JavaScript object
[
{
"familyName": "Smith",
"children": [
{ "firstName": "John" },
{ "firstName": "Mike" }
]
},
{
"familyName": "Williams",
"children": [
{ "firstName": "Mark" },
{ "firstName": "Dave" }
]
},
{
"familyName": "Jones",
"children": [
{ "firstName": "Mary" },
{ "firstName": "Sue" }
]
}
]
I’d like to create an array of all children i.e.
[
{ "FirstName": "John" },
{ "FirstName": "Mike" },
{ "FirstName": "Mark" },
{ "FirstName": "Dave" },
{ "FirstName": "Mary" },
{ "FirstName": "Sue" }
]
I am using jQuery.
I have looked at posts that describe merging or concatenating arrays but not those of child arrays: e.g. Merge/flatten an array of arrays in JavaScript?
I believe I could loop through the families and add the children arrays but suspect that there is a 'one-liner' for this?
I tested in the console:
//The families(duh)
const families = [
{
"familyName": "Smith",
"children": [
{ "firstName": "John" },
{ "firstName": "Mike" }
]
},
{
"familyName": "Williams",
"children": [
{ "firstName": "Mark" },
{ "firstName": "Dave" }
]
},
{
"familyName": "Jones",
"children": [
{ "firstName": "Mary" },
{ "firstName": "Sue" }
]
}
]
//Just flatten the children:
var children = [].concat.apply([], families.map(family => family.children));
//Outputs
console.log(children);
A solution without jQuery would be to use reduce to extract children from their families (sounds a bit rough, sorry for that).
families.reduce(function(list, family){
return list.concat(family.children);
}, []);
You can do this by using $.map:
var a = [
{
"familyName": "Smith",
"children": [
{ "firstName": "John" },
{ "firstName": "Mike" }
]
},
{
"familyName": "Williams",
"children": [
{ "firstName": "Mark" },
{ "firstName": "Dave" }
]
},
{
"familyName": "Jones",
"children": [
{ "firstName": "Mary" },
{ "firstName": "Sue" }
]
}
]
console.log($.map(a, function(it){
return it.children;
}));
// Or ES6
$.map(a, it => it.children);
Result:
[
{
"firstName":"John"
},
{
"firstName":"Mike"
},
{
"firstName":"Mark"
},
{
"firstName":"Dave"
},
{
"firstName":"Mary"
},
{
"firstName":"Sue"
}
]
Try with Array#forEach method .then push the children object with new array
var families = [ { "familyName": "Smith", "children": [ { "firstName": "John" }, { "firstName": "Mike" } ] }, { "familyName": "Williams", "children": [ { "firstName": "Mark" }, { "firstName": "Dave" } ] }, { "familyName": "Jones", "children": [ { "firstName": "Mary" }, { "firstName": "Sue" } ] } ]
var children = [];
families.forEach(family => family.children.forEach(child => children.push(child)));
console.log(children);