How to get the Uniq objects Using javascript or lodash - javascript

i am having the Array of objects like this
var result={
"employees": [
{
"_id": "5796e7a27d075bd0453b7751",
"firstName": "Test4",
"schemaName": "Employee"
},
{
"_id": "5796e78e7d075bd0453b774f",
"firstName": "Test 3",
"schemaName": "Employee"
},
{
"_id": "5790b203df5ad69025e8a20b",
"email": "df#gmail.com",
"schemaName": "Employee"
},
{
"_id": "577f69cc789df5ec1e995513",
"firstName": "Jeevan",
"email": "ddd#asd.com",
"schemaName": "Employee"
},
{
"_id": "577f69cc789df5ec1e995513",
"firstName": "Chethan",
"email": "ddd#asd.com",
"schemaName": "Employee"
}
]
};
};
but i want uniq objects by email. i am using lodash uniq but its Not giving proper Result. here i tried this code.
var combined=result.employees.map(function(employee){
employee.schemaName='Employee';
return employee;
});
combined = _.uniq(combined, 'email');
console.log(combined);
The Result is coming like this.
[ { _id: '5796e7a27d075bd0453b7751',
firstName: 'Test4',
schemaName: 'Employee' },
{ _id: '5790b203df5ad69025e8a20b',
email: 'df#gmail.com',
schemaName: 'Employee' },
{ _id: '577f69cc789df5ec1e995513',
firstName: 'Jeevan',
email: 'ddd#asd.com',
schemaName: 'Employee' } ]
i want the objects which are not having email ids and i want only objects which are unique emailid's can anybody help me on this. I want the Result contain the objects Which are not having email id also. The Result should be like this.
[ { _id: '5796e7a27d075bd0453b7751',
firstName: 'Test4',
schemaName: 'Employee' },
{ _id: '5796e78e7d075bd0453b774f',
firstName: 'Test3',
schemaName: 'Employee' },
{ _id: '5790b203df5ad69025e8a20b',
email: 'df#gmail.com',
schemaName: 'Employee' },
{ _id: '577f69cc789df5ec1e995513',
firstName: 'Jeevan',
email: 'ddd#asd.com',
schemaName: 'Employee' } ]

This could make it too.
_.uniqBy(result.employees, function(employee){return employee.email || employee._id;});

I would recommend the use of _.uniqWith for this with your own comparator.
var result = {
"employees": [
{
"_id": "5796e7a27d075bd0453b7751",
"firstName": "Test4",
"lastName": "T",
"__v": 0,
"schemaName": "Employee"
},
{
"_id": "5796e78e7d075bd0453b774f",
"firstName": "Test 3",
"lastName": "T",
"__v": 0,
"schemaName": "Employee"
},
{
"_id": "5796e77e7d075bd0453b774d",
"firstName": "Test 2",
"lastName": "T",
"__v": 0,
"documents": [],
"schemaName": "Employee"
},
{
"_id": "5796e7707d075bd0453b774b",
"firstName": "Test1",
"lastName": "T",
"__v": 0,
"schemaName": "Employee"
},
{
"_id": "5790b203df5ad69025e8a20b",
"firstName": "Ganesh",
"lastName": "dsf",
"__v": 0,
"email": "df#gmail.com",
"schemaName": "Employee"
},
{
"_id": "577f69cc789df5ec1e995513",
"firstName": "Jeevan",
"__v": 0,
"email": "fs#asf.com",
"schemaName": "Employee"
},
{
"_id": "577f69cc789df5ec1e995513",
"firstName": "Chethan",
"__v": 0,
"email": "fs#asf.com",
"schemaName": "Employee"
}
]
};
// Create a lodash chain from the employees.
combined = _.uniqWith(result.employees, function(e1, e2){
return e1.email && e1.email === e2.email;
});
console.log(combined);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.14.0/lodash.min.js"></script>

I'm using a deepEquals algorithm so this code becomes more general. If you want to check only by email, just change the equals function below.
const equals =
// Naïve deepEquals, only for demo. Doesn't work if keys orders vary.
(obj1, obj2) => JSON.stringify(obj1) === JSON.stringify(obj2);
// A real deepEquals:
// https://www.npmjs.com/package/fast-deep-equal
const uniq = (el1, index1, array) =>
array.every((el2, index2) => index1 <= index2 || !equals(el1, el2));
[{ a: 1, b: 2 }, { c: 3 }, { a: 1, b: 2 }, { d: 4 }, { a: 1, b: 2 }].filter(uniq);
// Result: [ { a: 1, b: 2 }, { c: 3 }, { d: 4 } ]

Related

What is the best way to find if there are any duplicates in nested child property in a JavaScript Object?

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.';
}
}
}

how to remove sessionID:null value objects from the array nested inside the array of objects in js

[
{
"_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
}
})

Loop through nested json array to create new array

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);

How to merge children in multiple JSON objects?

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);

Need help in lodash combinations to get the below object

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>

Categories

Resources