Filtering object on keys - javascript

I am getting the data from SQL using GROUP CONCAT.
What I finally want to achieve is Output expected. I tried using filter and map but couldn't achieve the desired output.
How can we achieve this so as to get serviceObj contain the array of objects
Output expected
var a = [
{
"id": 1,
"membership_name": "basic",
"membership_price": "10",
"serviceObj" :[
{id :7, name:Multi-City Artisan Availability}, {id:3,name:Hair and/or Makeup},{id:6,Online Booking. Easy},{id:5, name:On Location. Whenever. Wherever},{id:4,name:2 Services / Month with Rollover}
],
} ..so on for 2 ids ]
INPUT
var a = [
{
"id": 1,
"membership_name": "basic",
"membership_price": "10",
"services_id": "7;3;6;5;4",
"services_names": "Multi-City Artisan Availability;Hair and/or Makeup;Online Booking. Easy;On Location. Whenever. Wherever;2 Services / Month with Rollover"
},
{
"id": 2,
"membership_name": "Elite",
"membership_price": "123",
"services_id": "10;9;12;8;11",
"services_names": "2 Services / Month with Rollover;Hair and/or Makeup;Online Booking. Easy;Personal Makeup Shopper (1 appt);On Location. Whenever. Wherever."
},
{
"id": 3,
"membership_name": "Exclusive",
"membership_price": "169",
"services_id": "14;17;13;20;16;19;15;18",
"services_names": "2 Services / Month with Rollover;Online Booking. Easy;Hair and/or Makeup;Choice of Updo / Downdo Hairstyle;On Location. Whenever. Wherever;Faux Lashes & Airbrush Included;Personal Makeup Shopper (1 appt);Multi-City Artisan Availability"
},
{
"id": 4,
"membership_name": "Life",
"membership_price": "7999.20",
"services_id": "21;30;25;29;24;27;23;26",
"services_names": "VALID FOR LIFE!;Personalized Customer Care;Online Booking. Easy.;Choice of Updo / Downdo Hairstyle;On Location. Whenever. Wherever.;Faux Lashes & Airbrush Included;Hair and/or Makeup **;Multi-City Artisan Availability"
}
];
var obj = {};
var k = [];
l = a.map(n=>{
var obj = {
id : n.id,
membership_name : n.membership_name,
membership_price : n.membership_price,
service : [
{services_id : n.services_id,services_names:n.services_names }
]
}
k.push(obj);
})
console.log(JSON.stringify(k));

If you split out the ids and names you can then map over them to create a serviceObj array that you can add to the returned object array:
const out = a.map(({ id, membership_name, membership_price, services_id, services_names }) => {
const ids = services_id.split(';');
const names = services_names.split(';');
const serviceObj = ids.map((id, i) => ({ id: Number(id), name: names[i]}));
return { id, membership_name, membership_price, serviceObj }
});

For every item in an a array, Array.prototype.split() its services_id and services_name fields on the ;. Assuming they both will have the same length, iterate both of them in parallel and create new array of objects, based on the fields from both of the arrays.
var a = [
{
"id": 1,
"membership_name": "basic",
"membership_price": "10",
"services_id": "7;3;6;5;4",
"services_names": "Multi-City Artisan Availability;Hair and/or Makeup;Online Booking. Easy;On Location. Whenever. Wherever;2 Services / Month with Rollover"
},
{
"id": 2,
"membership_name": "Elite",
"membership_price": "123",
"services_id": "10;9;12;8;11",
"services_names": "2 Services / Month with Rollover;Hair and/or Makeup;Online Booking. Easy;Personal Makeup Shopper (1 appt);On Location. Whenever. Wherever."
},
{
"id": 3,
"membership_name": "Exclusive",
"membership_price": "169",
"services_id": "14;17;13;20;16;19;15;18",
"services_names": "2 Services / Month with Rollover;Online Booking. Easy;Hair and/or Makeup;Choice of Updo / Downdo Hairstyle;On Location. Whenever. Wherever;Faux Lashes & Airbrush Included;Personal Makeup Shopper (1 appt);Multi-City Artisan Availability"
},
{
"id": 4,
"membership_name": "Life",
"membership_price": "7999.20",
"services_id": "21;30;25;29;24;27;23;26",
"services_names": "VALID FOR LIFE!;Personalized Customer Care;Online Booking. Easy.;Choice of Updo / Downdo Hairstyle;On Location. Whenever. Wherever.;Faux Lashes & Airbrush Included;Hair and/or Makeup **;Multi-City Artisan Availability"
}
];
var output = a.map((item) => {
var ids = item.services_id.split(';');
var names = item.services_names.split(';');
var objects = [];
ids.forEach((id, index) => {
objects.push({
id : parseInt(id),
name: names[index]
});
});
return {
"id": item.id,
"membership_name": item.membership_name,
"membership_price": item.membership_price,
"serviceObj": objects
}
});
console.log(output);

Related

How to get this output from JSON in javascipt ny comparing student_id from mark_details and students_detail?

JSON Object:
{
"students_detail": [
{
"student_id": 1,
"name": "abc",
"roll_number": 10
},
{
"student_id": 2,
"name": "pqr",
"roll_number": 12
}
],
"subject_details": [
{
"subject_id": 1,
"subject_name": "math"
},
{
"subject_id": 2,
"subject_name": "english"
}
],
"exam_details": [
{
"exam_id": 1,
"exam_name": "Prelim"
}
],
"mark_details": [
{
"id": 1,
"exam_id": 1,
"subject_id": 1,
"student_id": 1,
"mark": 51
},
{
"id": 2,
"exam_id": 1,
"subject_id": 2,
"student_id": 2,
"mark": 61
}
]
}
Ouptut:
{
"student_mark_details": [
{
"abc": {
"roll_number": 10,
"Prelim": [
{
"subject_name": "math",
"mark": 51
}
]
},
"pqr": {
"roll_number": 12,
"Prelim": [
{
"subject_name": "english",
"mark": 61
}
]
}
}
]
}
i tried using loops and accesing student_id in both object and comparing them but code gets too messy and complex,is there any way i can use map() or filter() in this or any other method.
i have no idea where to start,my brain is fried i know im asking lot but help will be appreciated (any link/source where i can learn this is fine too)
Your output object really has a weird format: student_mark_details is an array of size 1 that contains an object that has all your students in it. Anyway, this should give you what you need. It is a format that you find often because it is a system with primary key and secondary key used a lot in databases.
The key to manage that is to start with what is at the core of what you are looking for (here, you want to describe students, so you should start from there), and then navigate the informations you need by using the primary/secondary keys. In JS, you can use the find() function in the case where one secondary key can be linked only to one primary key (ex: one mark is linked to one exam), and the filter() function when a secondary key can be linked to multiple secondary keys (ex: a student is linked to many grades).
I am not sure if this is 100% what you need because there are maybe some rules that are not shown in your example, but it solves the problem you submitted here. You might have to test it and change it depending of those rules. I don't know what your level is so I commented a lot
const data = {
"students_detail": [
{
"student_id": 1,
"name": "abc",
"roll_number": 10
},
{
"student_id": 2,
"name": "pqr",
"roll_number": 12
}
],
"subject_details": [
{
"subject_id": 1,
"subject_name": "math"
},
{
"subject_id": 2,
"subject_name": "english"
}
],
"exam_details": [
{
"exam_id": 1,
"exam_name": "Prelim"
}
],
"mark_details": [
{
"id": 1,
"exam_id": 1,
"subject_id": 1,
"student_id": 1,
"mark": 51
},
{
"id": 2,
"exam_id": 1,
"subject_id": 2,
"student_id": 2,
"mark": 61
}
]
}
function format(data) {
const output = {
"student_mark_details": [{}]
};
//I start by looping over the students_detail because in the output we want a sumary by student
data.students_detail.forEach(student => {
//Initialization of an object for a particular student
const individualStudentOutput = {}
const studentId = student.student_id;
const studentName = student.name;
//The rollNumber is easy to get
individualStudentOutput.roll_number = student.roll_number;
//We then want to find the exams that are linked to our student. We do not have that link directly, but we know that our student is linked to some marks
//Finds all the marks that correspond to the student
const studentMarkDetails = data.mark_details.filter(mark => mark.id === studentId);
studentMarkDetails.forEach(individualMark => {
//Finds the exam that corresponds to our mark
const examDetail = data.exam_details.find(exam => individualMark.exam_id === exam.exam_id);
//Finds the subject that corresponds to our mark
const subjectDetail = data.subject_details.find(subject => individualMark.subject_id === subject.subject_id);
//We then create a grade that we will add to our exam
const grade = {
subject_name: subjectDetail.subject_name,
mark: individualMark.mark
}
//We then want to add our grade to our exam, but we don't know if our output has already have an array to represent our exam
//So in the case where it does not exist, we create one
if (!individualStudentOutput[examDetail.exam_name]) {
individualStudentOutput[examDetail.exam_name] = [];
}
//We then add our grade to the exam
individualStudentOutput[examDetail.exam_name].push(grade);
});
//Now that we have finished our individual output for a student, we add it to our object
output.student_mark_details[0][studentName] = individualStudentOutput;
})
return output;
}
console.log(JSON.stringify(format(data)))

I need to fetch that 2nd query "Total Job" column with the first query as per the account_id is the primary key. How can I combine this two queries?

I need to fetch that 2nd query "Total Job" column with the first query as per the account_id is the primary key. How can I combine this two queries?
This is my Typescript NodeJS and mysql Rest API. How can I get this result?
const getPremiumJob = async (req: Request) => {
const connection = await createConnection()
try {
console.log(1)
const [premiumJob]: any = await connection.query(`SELECT rafp.account_id,rafp.foa_property_id,fpl.name,
rafp.text_value,rafp.int_value,rafp.float_value, fp.datatype FROM
rel_account_foa_property rafp join foa_property_localization fpl on rafp.foa_property_id=fpl.foa_property_id join
account on account.account_id=rafp.account_id inner join foa_property fp on fp.foa_property_id=rafp.foa_property_id where
fpl.name IN ('job title','enterprise','job description','job description','adress','image','job type','company_youtube','cover image') order by rafp.account_id ;`)
// const [premiumJob]: any = await connection.query(`SELECT t.tender_id,fpl.foa_property_id,fpl.name,rtfp.text_value,rtfp.int_value,rtfp.float_value, fp.datatype FROM tender t
// inner join rel_tender_foa_property rtfp on t.tender_id= rtfp.tender_id inner join foa_property_localization fpl on fpl.foa_property_id=rtfp.foa_property_id
// inner join foa_property fp on fp.foa_property_id=rtfp.foa_property_id `)
const [premiumJobCount]: any = await connection.query(` SELECT rel_account_foa_property.account_id,rel_account_foa_property.foa_property_id,rel_account_foa_property.text_value as "company name",COUNT(text_value) as "Total Job" FROM rel_account_foa_property join foa_property_localization on rel_account_foa_property.foa_property_id=foa_property_localization.foa_property_id join account on account.account_id=rel_account_foa_property.account_id where
foa_property_localization.name="enterprise" group by rel_account_foa_property.account_id,rel_account_foa_property.foa_property_id;`)
console.log(premiumJob)
const values = premiumJob.reduce((prev: any, curr: any) => ({
...prev,
[curr.account_id]: {
account_id: curr.account_id,
...prev[curr.account_id],
[(curr.name).replaceAll(' ', "_")]: curr[`${curr.datatype}_value`],
}
}), {}
as Record < string, any > )
return Object.values(values)
} catch (error) {
await connection.end()
throw error
}
}
I am getting below this result when I excecated first query
{
"account_id": 2641,
"job_title": "test1",
"enterprise": "hh",
"job_description": "test1",
"adress": "bangalore",
"image": "http://localhost:3005/public/uploads/company-logos/undefined",
"job_type": "top",
"company_youtube": "test2",
"cover_image": "http://localhost:3005/public/uploads/company-logos/undefined"
}
I Need also Total Job from the second query add with this above query account_ID
I expected output is given below
{
"account_id": 2639,
"job_title": "test1",
"enterprise": "hh",
"job_description": "test1",
"adress": "bangalore",
"image": "http://localhost:3003/public/uploads/company-logos/undefined",
"job_type": "top",
"company_youtube": "test2",
"cover_image": "http://localhost:3003/public/uploads/company-logos/undefined",
"Total Job": 1
}, {
"account_id": 2641,
"job_title": "test1",
"enterprise": "hh",
"job_description": "test1",
"adress": "bangalore",
"image": "http://localhost:3005/public/uploads/company-logos/undefined",
"job_type": "top",
"company_youtube": "test2",
"cover_image": "http://localhost:3005/public/uploads/company-logos/undefined",
"Total Job": 1
}

convert all array object(firestore timestamp) to date

I am using firestore and react-native-gifted-chat, I am trying to get all the chat messages from firestore to the chat. However, gifted chat does not support displaying firebase timestamp. It will show invalid Date. Therefore, I m trying to convert all the date object.
async _getMessage() {
const messColRef = db.collection('Message').doc(this.state.roomName).collection('message').orderBy('createdAt', 'desc').limit(9)
const initialQuery = messColRef
const documentSnapshots = await initialQuery.get()
const documentData = documentSnapshots.docs.map(document => ({
id: document.id, ...document.data()
}));
const lastVisible = documentData[documentData.length - 1]
const finalData = _.forEach(documentData['createdAt'], (item) => {
return item.toDate()
});
console.log(documentData)
}
and it is how my data look like:
{
"_id": "f0feb0b6-c0f9-4735-a93d-4297872a4840",
"createdAt": Timestamp {
"nanoseconds": 382000000,
"seconds": 1568995812,
},
"id": "Uw6PNNsf7aqWrxcgSDSi",
"text": "Hi",
"user": {
"_id": "V8h2iSllhPXSr8sTGP0yHiaYZwx1",
"avatar": "https://firebasestorage.googleapis.com/v0/b/exit-3684f.appspot.com/o/add-
user.png ? alt = media & token=395c8beb - 47a3 - 4ae6 - a0a1 - fe901e7ad42f",
"name": "This is the username",
},
},
{
"_id": "cc298d96-f19a-4ec7-bdf7-3767d900a364",
"createdAt": Timestamp {
"nanoseconds": 373000000,
"seconds": 1568995733,
},
"id": "WzbOA52Y3qukvPUIXRLB",
"text": "hello",
"user": {
"_id": "V8h2iSllhPXSr8sTGP0yHiaYZwx1",
"avatar": "https://firebasestorage.googleapis.com/v0/b/exit-3684f.appspot.com/o/add-
user.png ? alt = media & token=395c8beb - 47a3 - 4ae6 - a0a1 - fe901e7ad42f",
"name": "This is the username",
},
},
so my goal is to convert all the createdAt to js time date
Sorry for not explore deeply, after checking #Spatz comments I figure out how to do it
documentData.forEach(a => {
var date = a.createdAt.toDate()
data.push({
_id: a._id,
createdAt: date,
id: a.id,
text: a.text,
user: a.user
})
})
Use renderTime prop of gifted chat and pass a function which converts the time and return that time in a string.

Filter objects based on a match in another array

I am trying to use Lodash to filter an array of objects based on a match of id's, this is what I have tried:
var team = _.find(this.teams, { 'id': this.newSchedule.team});
_.filter(this.yards, function(yard) {
return _.find(team.yards, { id: yard.id });
});
yards data:
[ { "id": 1, "name": "Test" },{ "id": 2, "name": "Test 2" } ]
team data:
[ { "id": 1, "name": "Team 1", "yards": [{ "id": 1, "name" }] ]
I want this.yards to show the yards based on the yard id from a selected team.
Its hard to understand what you mean, does the yard id match the team id?
If so it sounds like what you need to do is first find the team with the same id then grab that teams yards. Therefore I would use the map function twice:
const result = this
.yards
.map(y => team.find(t => t.id === y.id)) // join with the right team
.map(t => t.yards) // reduce to that teams yards
As team is an array, you need to iterate it before doing the _.find on an individual element in that array. It doesn't help that you called your variable team (singular). teams would make more sense.
Here is how you would change your lodash code:
var yards = [ { id: 1, name: "Test" },{ id: 2, name: "Test 2" } ],
teams = [ { id: 1, name: "Team 1", yards: [{ id: 1, name: "Missing string" }] } ]
result = _.filter(this.yards, function(yard) {
return _.some(this.teams, function(team) {
return _.find(team.yards, { id: yard.id });
});
});
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.16.4/lodash.min.js"></script>
So this returns the yards that are related to at least one team.

Javascript: Printing array of a constructor class

Posting only the parts needed.
// This program simulates purchases of musical albums through a loop.
// The user initially has 1000 dollars. As the program loops through the albums
// the user purchases random quantities. The program adds the subtotals and
// subtracts from the initial total to find out what the user has left.
// Variables for random quantity.
var min = 1,
max = 25;
// Constructor for Album class
function Album(title, artist, price, release){
this.title = title;
this.artist = artist;
this.price = price;
this.release = release;
this.quantity = (Math.floor(Math.random() * max) + min);
this.subtotal = this.quantity * this.price;
};
Album.prototype.purchase = function(){
this.quantity--;
if (this.quantity > 0){
return 1;
}
else{
return -1;
}
};
// Constructor for Cart class
function Cart(val){
this.items = [];
};
Cart.prototype.add = function(val){
this.items.push(val);
};
Cart.prototype.remove = function(val){
this.items.splice(albums.indexOf(val), 1);
};
// Object that inherit from the Album class.
var nothingSame = new Album('Nothing Was the Same', "Drake", 15.99, "09/24/2013");
nothingSame.tracklisting = ["Started from the Bottom", "All Me", "Pound Cake", "The Language"];
var lifeOfPablo = new Album("The Life of Pablo", "Kanye West", 15.98, "02/14/2016");
lifeOfPablo.tracklisting = ["Ultralight Beam", "Famous", "Feedback", "Low Lights"];
var babel = new Album("Babel", "Mumford & Sons", 13.83, "09/21/2012");
babel.tracklisting = ["I Will Wait", "Lover of the Light", "Whispers in the Dark", "Babel"];
var ghostStories = new Album("Ghost Stories", "Coldplay", 12.61, "05/16/2014");
ghostStories.tracklisting = ["Magic", "Midnight", "A Sky Full of Stars", "True Love"];
var trueAlbum = new Album("True", "Avicii", 15.99, "09/13/2013");
trueAlbum.tracklisting = ["Wake Me Up", "You Make Me", "Hey Brother", "Lay Me Down"];
// Array of the albums for the objects within them.
var albums = [nothingSame, lifeOfPablo, babel, ghostStories, trueAlbum];
//Variables the initial amount of money
var INITIAL_MONEY = 1000.00;
var n = 1000.00;
// Instance of cart.
var cart = new Cart();
// Loop that simulates the purchase.
var i = 0;
while(INITIAL_MONEY > 0 && i < albums.length){
if (INITIAL_MONEY >= albums[i].subtotal){
albums[i].purchase();
INITIAL_MONEY = INITIAL_MONEY - albums[i].subtotal;
cart.add(albums[i]);
}
i++;
}
// Variable for the total amount spent.
var total = n - INITIAL_MONEY;
// Console logs to output all the data to the user.
console.log("You walk into a store with $1000 and purchase several albums.")
console.log(cart);
console.log("Total: " + total.toFixed(2));
console.log("Money Remaining: " + INITIAL_MONEY.toFixed(2));
Output Example:
You walk into a store with $1000 and purchase several albums.
Cart {
items:
[ Album {
title: 'Nothing Was the Same',
artist: 'Drake',
price: 15.99,
release: '09/24/2013',
quantity: 22,
subtotal: 367.77,
tracklisting: [Object] },
Album {
title: 'The Life of Pablo',
artist: 'Kanye West',
price: 15.98,
release: '02/14/2016',
quantity: 1,
subtotal: 31.96,
tracklisting: [Object] },
Album {
title: 'Babel',
artist: 'Mumford & Sons',
price: 13.83,
release: '09/21/2012',
quantity: 1,
subtotal: 27.66,
tracklisting: [Object] },
Album {
title: 'Ghost Stories',
artist: 'Coldplay',
price: 12.61,
release: '05/16/2014',
quantity: 4,
subtotal: 63.05,
tracklisting: [Object] },
Album {
title: 'True',
artist: 'Avicii',
price: 15.99,
release: '09/13/2013',
quantity: 18,
subtotal: 303.81,
tracklisting: [Object] } ] }
Total: 794.25
Money Remaining: 205.75
I can't figure out how to get the track listing to show. Closest I got to it, it only showed the last track in the array for all of them. I can't seem to get each of the albums to display the listed tracks in the output.
If you want to output this for debugging or toString purposes, you can try JSON.stringify(albums, null, 2).
If you want it displayed in the console, using console.log, try console.log(JSON.stringify(albums, null, 2))
Edit:
Applied to your Cart implementation, use console.log(JSON.stringify(cart, null, 2)) in place of console.log(cart).
Sample output
{
"items": [
{
"title": "Nothing Was the Same",
"artist": "Drake",
"price": 15.99,
"release": "09/24/2013",
"quantity": 18,
"subtotal": 303.81,
"tracklisting": [
"Started from the Bottom",
"All Me",
"Pound Cake",
"The Language"
]
},
{
"title": "The Life of Pablo",
"artist": "Kanye West",
"price": 15.98,
"release": "02/14/2016",
"quantity": 15,
"subtotal": 255.68,
"tracklisting": [
"Ultralight Beam",
"Famous",
"Feedback",
"Low Lights"
]
},
{
"title": "Babel",
"artist": "Mumford & Sons",
"price": 13.83,
"release": "09/21/2012",
"quantity": 16,
"subtotal": 235.11,
"tracklisting": [
"I Will Wait",
"Lover of the Light",
"Whispers in the Dark",
"Babel"
]
},
{
"title": "True",
"artist": "Avicii",
"price": 15.99,
"release": "09/13/2013",
"quantity": 10,
"subtotal": 175.89000000000001,
"tracklisting": [
"Wake Me Up",
"You Make Me",
"Hey Brother",
"Lay Me Down"
]
}
]
}
If you just want to dump the contents of the created object to console, then it's not much of a js problem, but more of dealing with quirks of the console you're using... E.g. some consoles collapse nested objects.
In most cases you can dump the objects to string and output that, it's a good debugging aproach (which additionally gives you a view of an object from the time of the console call execution, not a reference to an object that might change later):
JSON.stringify(albums);
so in typical console call:
console.log(JSON.stringify(albums));
Looping through the album instances tracklisting property manually, you can get the individual items:
// Loop over the albums array
for(var i = 0; i < albums.length; ++i){
// Loop through the tracklisting array elements for the current album
for(var x = 0; x < albums[i].tracklisting.length; ++x){
console.log(albums[i].tracklisting[x]);
}
}
But, how about:
var albumString = JSON.stringify(albums);
console.log(albumString);
To simply turn the entire object structure into a string?

Categories