I have a large array of users which are comprised of 3 different user types ("Admin", "Moderator", "User"). Each user will have the following properties: ("name", "companyId", "type").
The first method will take 1 parameter: an array of users and must return a grouped list according to the user property "type".
The second method will take 4 parameters: a grouped list (result from the first method), an array of user types to include in the search, a string representing the user property to filter by and a string representing the value of the user property. This method must return an array of users as per the search parameters.
My method constructions are returning weird results. Could someone help?
let userTypes = ["Admin", "Moderator", "User"]
function orchestrateUsers(users) {
let result = [];
users.forEach(user => {
result.push({
"name": user.name,
"type": user.type
});
});
return result;
}
function searchUsers(orchestratedUsers, userTypes, property, value) {
}
const users= [{
"name": "Joe",
"companyId": "A2100",
"type": "Admin"
},
{
"name": "Jane",
"companyId": "A2100",
"type": "Moderator"
},
{
"name": "Smith",
"companyId": "A2100",
"type": "User"
},
{
"name": "Smith",
"companyId": "A2100",
"type": "User"
},
{
"name": "Rocket",
"companyId": "A3100",
"type": "Admin"
},
{
"name": "Rick",
"companyId": "A3100",
"type": "User"
},
{
"name": "Tim",
"companyId": "A4100",
"type": "Admin"
}
]
console.log(orchestrateUsers(users));
Answering the first question
const users = [{ "name": "Joe", "companyId": "A2100", "type": "Admin" }, { "name": "Jane", "companyId": "A2100", "type": "Moderator" }, { "name": "Smith", "companyId": "A2100", "type": "User" }, { "name": "Smith", "companyId": "A2100", "type": "User" }, { "name": "Rocket", "companyId": "A3100", "type": "Admin" }, { "name": "Rick", "companyId": "A3100", "type": "User" }, { "name": "Tim", "companyId": "A4100", "type": "Admin" } ]
function orchestrateUsers(users) {
let result = {};
users.forEach(user => {
if (result[user.type]) result[user.type].push(user.name);
else result[user.type] = [user.name];
});
return result;
}
console.log(orchestrateUsers(users));
It looks like you want something like lodash. Here's an example using _.groupBy to group users by type & _.filter to filter for admins:
const users = [
{"name": "Joe", "companyId": "A2100", "type": "Admin"},
{"name": "Jane", "companyId": "A2100", "type": "Moderator"},
{"name": "Smith", "companyId": "A2100", "type": "User"},
{"name": "Rick", "companyId": "A3100", "type": "User" }
];
var usersByType = _.groupBy(users, function (user) {
return user.type;
});
console.log(usersByType);
var admins = _.filter(users, function(user) {
return user.type === "Admin";
});
console.log(admins);
console.log(Object.keys(usersByType));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
Run the code snippet to see the console output.
Why Lodash?
Lodash makes JavaScript easier by taking the hassle out of working
with arrays, numbers, objects, strings, etc. Lodash’s modular methods
are great for:
Iterating arrays, objects, & strings
Manipulating & testing values
Creating composite functions
Related
i have a array of object i need to join all into one single object as parent child
for example
let array= [
{
"Gender": "male",
"Type": "backpacks",
"Key": "size",
"Values": "small,large,medium"
},
{
"Gender": "male",
"Type": "backpacks",
"Key": "strap",
"Values": "padded,non-padded"
},
{
"Gender": "female",
"Type": "backpacks",
"Key": "pocket",
"Values": "multiple,zip,buckle"
},
{
"Gender": "female",
"Type": "backpacks",
"Key": "size",
"Values": "small,large,medium"
},
{
"Gender": "female",
"Type": "sunglasses",
"Key": "size",
"Values": "XL,XXL,XXL"
},
{
"Gender": "female",
"Type": "sunglasses",
"Key": "color",
"Values": "red,black,yellow"
},
]
expected output
let obj={
"male": {
"backpacks": {
"size": "small,large,medium",
"strap": "padded,non-padded"
},
},
"female": {
"backpacks": {
"size": "small,large,medium",
"strap": "padded,non-padded"
},
"sunglasses": {
"size": "XL,XXL,XXL",
"color": "red,black,yellow"
}
}
}
i tried created a blank object and a for loop then each iteration i added into that object but since it have more level of nest am not able to do
i tried using lodash _.flatten but now working as i expected
As you point out, since you are grouping the items at multiple depths, a lodash helper like _.groupBy won't work here, so you'll need to build the object yourself.
You can either reduce your array, or manually loop over it and build your object, whichever you find easier to understand.
I'll use an iterative approach since I'm guessing that'll be easier to understand.
function groupItems(items) {
let mainGroup = {};
for (let item of items) {
const { Gender, Type, Key, Values } = item;
// If we don't have an object to group by gender yet, create one
if (!mainGroup[Gender]) {
mainGroup[Gender] = {};
}
// If we don't have an object to group this gender's product yet, create one
if (!mainGroup[Gender][Type]) {
mainGroup[Gender][Type] = {};
}
// Finally, save the value under the (lowercased) key we received
mainGroup[Gender][Type][Key.toLowerCase()] = Values;
}
return mainGroup;
}
let array = [{"Gender":"male","Type":"backpacks","Key":"size","Values":"small,large,medium"},{"Gender":"male","Type":"backpacks","Key":"strap","Values":"padded,non-padded"},{"Gender":"female","Type":"backpacks","Key":"pocket","Values":"multiple,zip,buckle"},{"Gender":"female","Type":"backpacks","Key":"size","Values":"small,large,medium"},{"Gender":"female","Type":"sunglasses","Key":"size","Values":"XL,XXL,XXL"},{"Gender":"female","Type":"sunglasses","Key":"color","Values":"red,black,yellow"}];
console.log(groupItems(array));
Loop through the array, creating each nested object as needed, then filling in the Key: Values elements.
let array= [
{
"Gender": "male",
"Type": "backpacks",
"Key": "size",
"Values": "small,large,medium"
},
{
"Gender": "male",
"Type": "backpacks",
"Key": "strap",
"Values": "padded,non-padded"
},
{
"Gender": "female",
"Type": "backpacks",
"Key": "pocket",
"Values": "multiple,zip,buckle"
},
{
"Gender": "female",
"Type": "backpacks",
"Key": "size",
"Values": "small,large,medium"
},
{
"Gender": "female",
"Type": "sunglasses",
"Key": "size",
"Values": "XL,XXL,XXL"
},
{
"Gender": "female",
"Type": "sunglasses",
"Key": "color",
"Values": "red,black,yellow"
},
]
let obj = {};
array.forEach(({Gender, Type, Key, Values}) => {
if (!obj[Gender]) {
obj[Gender] = {};
}
if (!obj[Gender][Type]) {
obj[Gender][Type] = {};
}
obj[Gender][Type][Key] = Values;
});
console.log(obj);
INPUT:
let array =[
{name:"xyz", email:"xyz#gmail.com", date:"22/10/2020" },
{name:"abc", email:"abc#gmail.com", date:"29/12/2020" },
{name:"efg", email:"efg#gmail.com", date:"20/01/2021" },
{name:"pqr", email:"pqr#gmail.com", date:"12/08/2020", age:"20" },
{name:"stu", email:"stu#gmail.com", date:"19/09/2020", age:"21" },
]
After performing certain operations I got the above array of objects as output from mongodb collection. From that array I want to get all keys and compare each and every object in an array and if any property present in any object not there in another object then I want to assign the property with empty string value.
To perform that operation I have written the code as shown below-
const keys = array.reduce(
(acc, curr) => (Object.keys(curr).forEach((key) => acc.add(key)), acc),
new Set()
);
const output = array.map((item) =>
[...keys].reduce((acc, key) => ((acc[key] = item[key] ?? ""), acc), {})
);
By performing above operations along with my original keys I am getting unnecessary keys like "$__", "$isNew", "_doc"
MY OUTPUT:
[
{
"$__": {
"activePaths": {
"paths": {
"_id": "init"
},
"states": {
"ignore": {},
"default": {},
"init": {
"_id": true
},
"modify": {},
"require": {}
},
"stateNames": [
"require",
"modify",
"init",
"default",
"ignore"
]
},
"strictMode": false,
"skipId": true,
"selected": {},
"fields": {},
"exclude": null
},
"$isNew": false,
"_doc": {
"_id": "62e6791b049e103f612f0882",
"name": "pqr",
"email": "pqr#gmail.com",
"date": "12/8/2020",
"age": "20",
},
"name": "pqr",
"email": "pqr#gmail.com",
"date": "12/8/2020",
"age": "20",
},
.
.
.
.
EXPECTED OUTPUT:
[
{
"name": "xyz",
"email": "xyz#gmail.com",
"date": "22/10/2020",
"age": ""
},
{
"name": "abc",
"email": "abc#gmail.com",
"date": "29/12/2020",
"age": ""
},
{
"name": "efg",
"email": "efg#gmail.com",
"date": "20/01/2021",
"age": ""
},
{
"name": "pqr",
"email": "pqr#gmail.com",
"date": "12/08/2020",
"age": "20"
},
{
"name": "stu",
"email": "stu#gmail.com",
"date": "19/09/2020",
"age": "21"
}
]
If I am using same code for normal array instead of resultant array from mongoodb I am getting correct output.
Please help me in resolving the above issue.
Query
if you have few fields and you know their names you can do it on server like bellow, in simple way
check if field (if missing it will be false) if its there keep old value, else add it with ""
the bellow doesn't work with boolean fields, if you have those you should check if type="missing" but in your case you dont have boolean fields so it will be ok
Playmongo
aggregate(
[{"$set":
{"name": {"$cond": ["$name", "$name", ""]},
"email": {"$cond": ["$email", "$email", ""]},
"date": {"$cond": ["$date", "$date", ""]},
"age": {"$cond": ["$age", "$age", ""]}}}])
I have a response body that looks something like this:
{
"id": "provider-a7d49a99-53c0-4b7c-9be3-8b9efc828f1b",
"fullName": "Dr. Tim Lucca, FSE",
"firstName": "Tim",
"lastName": "Lucca",
"prefix": "Dr.",
"suffix": "FSE",
"phone": "(303) 520-4571",
"state": "CO",
"doseSpotID": 185012,
"active": "active",
"capabilities": {
"demographic": [
"adolescent",
"adult",
"child"
],
"geographic": [
"CO",
"TX"
],
"linguistic": [
"english",
"spanish"
],
"credentialedPayors": null
},
"invitePending": false
},
{
"id": "provider-450de310-fcb5-4e71-9d72-b6b320b2eb0a",
"fullName": "Mr Doc Torr",
"firstName": "Doc",
"lastName": "Torr",
"prefix": "Mr",
"suffix": "",
"phone": "(303) 520-4571",
"state": "CO",
"doseSpotID": 186856,
"active": "active",
"capabilities": {
"demographic": [
"adult",
"adolescent",
"child"
],
"geographic": [
"CO",
"TX"
],
"linguistic": [
"english"
],
"credentialedPayors": null
},
"invitePending": false
}
]
I have a search field for the user that they are able to search by fullName, phone, and geographic. Im trying to understand how to sort the list returned and display only the items in the list that have a match for the users input. What would be a good way to sort through the array of objects and creating an array of matches for the users search? Right now my component is just displaying all of the items returned.
for an exect match i would do this
let to_sort =
[
{
"id": "provider-a7d49a99-53c0-4b7c-9be3-8b9efc828f1b",
"fullName": "Dr. Tim Lucca, FSE",
"firstName": "Tim",
"lastName": "Lucca",
"prefix": "Dr.",
"suffix": "FSE",
"phone": "(303) 520-4571",
"state": "CO",
"doseSpotID": 185012,
"active": "active",
"capabilities": {
"demographic": [
"adolescent",
"adult",
"child"
],
"geographic": [
"CO",
"TX"
],
"linguistic": [
"english",
"spanish"
],
"credentialedPayors": null
},
"invitePending": false
},
{
"id": "provider-450de310-fcb5-4e71-9d72-b6b320b2eb0a",
"fullName": "Mr Doc Torr",
"firstName": "Doc",
"lastName": "Torr",
"prefix": "Mr",
"suffix": "",
"phone": "(303) 520-4571",
"state": "CO",
"doseSpotID": 186856,
"active": "active",
"capabilities": {
"demographic": [
"adult",
"adolescent",
"child"
],
"geographic": [
"CO",
"TX"
],
"linguistic": [
"english"
],
"credentialedPayors": null
},
"invitePending": false
}
]
let user_fullName = 'Dr. Tim Lucca, FSE'
let phone = '(303) 520-4571'
let geographic = 'CO'
let result = to_sort.filter((obj)=>{
if(obj.fullName !== user_fullName){
return false
}
if(obj.phone !== phone){
return false
}
if(!obj.capabilities.geographic.includes(geographic)){
return false
}
return true
});
to check if 1 of the properties is the same (not gonna put the data in is its quite big)
let user_fullName = 'Dr. Tim Lucca, FSE'
let phone = '(303) 520-4571'
let geographic = 'CO'
let result = to_sort.filter((obj)=>{
if(obj.fullName === user_fullName || obj.phone === phone || obj.capabilities.geographic.includes(geographic)){
return true
}
return false
});
in both cases result is an array of objects which have met the criteria
Having a thorny problem and only see similar but also simpler solutions on SO.
Is is possible to generate a dynamic key AND dynamic values using JS/JSON?
For instance, let's say I have JSON like this:
{
"email": "user#someco.com",
"firstname": "Bob",
"lastname": "Smith",
"company": "ACME",
"custom": {
"services": [
{
"name": "svc1",
"desc": "abcdefg",
"selected": "true",
"status": "None"
},
{
"name": "svc2",
"desc": "abcdefg",
"selected": "true",
"status": "None"
},
{
"name": "svc3",
"desc": "abcdefg",
"selected": "false",
"status": "None"
},
{
"name": "svc4",
"desc": "abcdefg",
"selected": "false",
"status": "None"
}
],
"fields": [
{
"name": "Products",
"desc": "abcdef",
"type": "multi",
"values": [
{
"name": "Product1",
"desc": "abcdef"
},
{
"name": "Product2",
"desc": "abcdef"
}
],
"services": [
"svc1",
"svc2",
"svc3"
]
},
{
"name": "Wines",
"desc": "abcdef",
"type": "multi",
"values": [
{
"name": "Wine 1",
"desc": "abcdef"
}
],
"services": [
"svc4"
]
},
{
"name": "Fruits",
"desc": "abcdef",
"type": "multi",
"values": [
{
"name": "Fruit 1",
"desc": "abcdef"
},
{
"name": "Fruit 2",
"desc": "abcdef"
}
],
"services": [
"svc4"
]
}
]
}
};
I need to go into the fields and for each field (products, wines, fruits) see if a given service is contained within so that I can go back and generate a product or wine or fruit for each service that requires it. But I don't want to repeat the services names more than once. The resulting JSON should look something like this:
{"svc1":["Products"], "svc2":["Products"], "svc3":["Products"], "svc4":["Fruits", "Wines"]}
The hope would be that to generate a dynamic list in Angular I can just turn and loop back through this JSON, pulling out the values for each product, fruit, wine, whatever.
I've been trying a lot of nested for loops and the like but whenever I get more than one layer down the dynamism seems to stop. I'm guessing that for this to work I need to move between JS Objects and JSON?
Right now I'm trying something like this, which isn't quite working, stringify or no. And maybe I'm flip-flopping too much between JSON and JS Objects:
var outObj = [];
var fieldItems;
$.each(jsonObj.custom.fields, function(key, item) {
fieldItems = item;
fieldItems.name = item.name;
$.each(fieldItems.services, function(key, item) {
var serviceName = item;
//check to see if the serviceName already exists
if (outObj.indexOf(serviceName) > -1) {
outObj.serviceName.push(fieldItems.name);
} else {
outObj.push(serviceName);
}
});
});
JSON.stringify(outObj);
console.log("outObj " + outObj);
I get "can't read property 'push' of undefined" errors and the like. Seems this should be possible from a single nested loop, but maybe I need to just do two passes? Any other suggestions?
To me it sounds like overcomplicated solution. You can use basic array methods of javascript to filter out required structure. I am not sure what profiling_value in the presented snippet, so I started from the object structure in OP
var desiredResult = jsonObj.custom.services.reduce(function(result, service){
result[service.name] = jsonObj.custom.fields.filter(function(field){
return field.services.indexOf(service.name) >= 0;
}).map(function(field){ return field.name; });
return result;
}, {});
This gives the expected result for mentioned object.
reduce is required to iterate over all services and accumulate result in one object. Then for each service fields are iterated to filter out only those that contain link to this service. And finally list of filtered fields is transformed (map) into list of strings - their names - and inserted into accumulator
trying to reference a field in this JSON but it's unlike anything in the examples I've been looking at so I'm kinda stumped.
I want to know how to reference the field at the end "HOW DO I REFERENCE THIS?". Thanks for any help.
var JSON =
{ "employees": {
"name" : "david",
"car" : "audi"
},
{
"name" : "jimmy",
"car" : "VW"
},
"customers" : {
"name" : "philip",
"purchase": "cabbage"
},
{
"name" : "Helen",
"purchase": "HOW DO I REFERENCE THIS?"
}
}
var x = "HOW DO I REFERENCE THIS?";
With the right syntax, which I believe you want this:
var JSON = {
"employees": [
{
"name": "david",
"car": "audi"
},
{
"name": "jimmy",
"car": "VW"
}],
"customers": [
{
"name": "philip",
"purchase": "cabbage"
},
{
"name": "Helen",
"purchase": "HOW DO I REFERENCE THIS?"
}]
}
You can get purchase by using this:
for (var i in JSON.customers)
{
var customer = JSON.customers[i];
var value = customer.purchase; // cabbage, HOW DO I...
}
try this:
var JSON = {
"employees": [{
"name": "david",
"car": "audi"
}, {
"name": "jimmy",
"car": "VW"
}],
"customers": [{
"name": "philip",
"purchase": "cabbage"
}, {
"name": "Helen",
"purchase": "HOW DO I REFERENCE THIS?"
}]
}
$.each(JSON.customers, function (k, data) {
alert(data.purchase);
});
Working Fiddle
Do you need to find the purchase string for "Helen" or just the second customer, if it's the second customer it will be (with valid JSON):
var string = '{"employees": [{"name": "david", "car": "audi"}, {"name": "jimmy", "car": "VW"}], "customers": [{"name": "philip", "purchase": "cabbage"}, {"name": "Helen", "purchase": "HOW DO I REFERENCE THIS?"}]}';
var string = JSON.parse(string);
console.log(string['customers'][1]['purchase']);
and if you need to find "Helen" it would be something like this (with valid JSON):
var string = '{"employees": [{"name": "david", "car": "audi"}, {"name": "jimmy", "car": "VW"}], "customers": [{"name": "philip", "purchase": "cabbage"}, {"name": "Helen", "purchase": "HOW DO I REFERENCE THIS?"}]}';
var string = JSON.parse(string);
for (var i=0 ; i < string['customers'].length ; i++) {
if (string['customers'][i]["name"] == "Helen") {
var result = string['customers'][i]['purchase'];
}
}
console.log(result);