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);
}
})
});
};```
CodePudding user response:
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));
CodePudding user response:
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
, notchilds
CodePudding user response:
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.';
}
}
}