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
}
})
I am working on a lambda function that GETs data from one API and POSTs it to another. The data is a list of contacts with properties, e.g. first name, last name, email, etc.
The JSON output contains too many properties that I don't need. See below code example (actual code contains many more properties and nested arrays/objects).
{
"contacts": [
{
"addedAt": 1532803458796,
"vid": 101
}
],
"merge-audits": [],
"properties": {
"first-name": {
"value":"hello"
},
"last-name": {
"value":"there"
},
"email": {
"value":"hello#there.com"
}
...
...
}
How can I loop through each JSON object to create a new, simpler JSON array like the following:
[
{
"email": "example#example.com",
"first_name": "",
"last_name": "User"
},
{
"email": "example2#example.com",
"first_name": "Example",
"last_name": "User"
}
]
Thanks in advance for your help.
try
json.map( x => ({
email: x.properties.email.value,
first_name: x.properties['first-name'].value,
last_name: x.properties['last-name'].value,
}));
let json = [
{
"contacts": [{
"addedAt": 1532803458796,
"vid": 101
}],
"merge-audits": [],
"properties": {
"first-name": {
"value": "hello"
},
"last-name": {
"value": "there",
},
"email": {
"value": "hello#there.com"
}
}
},
{
"contacts": [{
"addedAt": 1532803458796,
"vid": 101
}],
"merge-audits": [],
"properties": {
"first-name": {
"value": "Tom"
},
"last-name": {
"value": "Smith",
},
"email": {
"value": "tom#smith.com"
}
}
}
]
let r = json.map(x => ({
email: x.properties.email.value,
first_name: x.properties['first-name'].value,
last_name: x.properties['last-name'].value,
}));
console.log(r);
You could use a destructuring assignment for the object and short hand properties for the mapping.
var data = [{ contacts: [{ addedAt: 1532803458796, vid: 101 }], "merge-audits": [], properties: { "first-name": { value: "hello" }, "last-name": { value: "there" }, email: { value: "hello#there.com" } } }],
result = data.map(({ properties: {
'first-name': { value: first_name },
'last-name': { value: last_name },
email: { value: email }
} }) => ({ first_name, last_name, email }));
console.log(result);
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);
Below is my object First step is to check the socialAuth array of objects and get the platformName which has the showStats value as false.
I have accomplished the step1 as below
var arrList2 = _.pluck(_.where(creatorObj.socialAuth, {'showStats': false}), "platformName");
['Twitter'] is the output of the arrList2
var creatorObj =
{
"_id": "55e5b32f3874c964cc3dfe2e",
"firstName": "xyz",
"lastName": "abc",
"socialStats": [
{
"reach": 205976,
"_id": "asdfasdfasdf",
"profileUrl": null,
"engagements": 126,
"platformName": "Twitter"
}
],
"socialAuth": [
{
"screenName": "abc",
"userId": "12341234",
"_id": "55e5b3573874c964cc3dfe33",
"showStats": false,
"platformName": "Twitter"
},
{
"channelTitle": "xyz",
"channelId": "sdfgsdfgsdfg",
"_id": "55e5a040991c1321a5b9bd79",
"showStats": true,
"platformName": "Youtube"
}
]
};
Second step is to check the above arrList2 with the sociaStats array and remove the value from it and print the object again.
I need help in this second step.
I need the resulting object as
var creatorObj =
{
"_id": "55e5b32f3874c964cc3dfe2e",
"firstName": "xyz",
"lastName": "abc",
"socialStats": [],
"socialAuth": [
{
"screenName": "abc",
"userId": "12341234",
"_id": "55e5b3573874c964cc3dfe33",
"showStats": false,
"platformName": "Twitter"
},
{
"channelTitle": "xyz",
"channelId": "sdfgsdfgsdfg",
"_id": "55e5a040991c1321a5b9bd79",
"showStats": true,
"platformName": "Youtube"
}
]
};
You need to use _.remove() to remove the elements from array based on your condition.
Demo
var creatorObj = {
"_id": "55e5b32f3874c964cc3dfe2e",
"firstName": "xyz",
"lastName": "abc",
"socialStats": [{
"reach": 205976,
"_id": "asdfasdfasdf",
"profileUrl": null,
"engagements": 126,
"platformName": "Twitter"
}],
"socialAuth": [{
"screenName": "abc",
"userId": "12341234",
"_id": "55e5b3573874c964cc3dfe33",
"showStats": false,
"platformName": "Twitter"
}, {
"channelTitle": "xyz",
"channelId": "sdfgsdfgsdfg",
"_id": "55e5a040991c1321a5b9bd79",
"showStats": true,
"platformName": "Youtube"
}]
};
var arrList2 = _.pluck(_.where(creatorObj.socialAuth, {
'showStats': false
}), "platformName");
creatorObj.socialStats = _.remove(creatorObj.socialStats, function(n) {
return !_.includes(arrList2, n.platformName);
});
console.log(creatorObj);
document.write(JSON.stringify(creatorObj));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.js"></script>