Sort and manipulate array in javascript - javascript

I have the following array:
var curr = [{
"Year": 2019,
"Title": "Asset Management Sample",
"Sum": 1020000.0,
"Budget":0
}, {
"Year": 2019,
"Title": "Monday test 2",
"Sum": 2546658.0,
"Budget":100
}, {
"Year": 2020,
"Title": "Asset Management Sample",
"Sum": 1020000.0,
"Budget":1000
}, {
"Year": 2020,
"Title": "Monday test 2",
"Sum": 3472000.0,
"Budget":100
}, {
"Year": 2021,
"Title": "Asset Management Sample",
"Sum": 1020000.0,
"Budget":100
}, {
"Year": 2021,
"Title": "Monday test 2",
"Sum": 2452000.0,
"Budget":100
}]
That I need to change to:
[{
"Year": 2019,
"Asset Management Sample": 1020000.0,
"Monday test": 2546658.0
}, {
"Year": 2020,
"Asset Management Sample": 1020000.0,
"Monday test 2": 3472000.0
}, {
"Year": 2021,
"Asset Management Sample": 1020000.0,
"Monday test 2": 2452000.0
}]
With help from earlier posters I have used .reduce (slightly modified from below) to generate this:
var res = arr.reduce(function(acc, curr) {
acc[curr.Year] = acc[curr.Year];
acc[curr.Year] = acc[curr.Year] || { Year: curr.Year } ;
acc[curr.Year][curr.Title] = curr.Sum;
return acc;
I need to expand this to include a sum of all the budget values for each year (there should be a single budget value per year). I added the following line in before the return:
acc[curr.Year][curr.Budget] = curr[curr.Budget] || { Budget: curr.Budget } ;
It is adding individual entries for each Budget value. How do I sum the Budget values and return it without affecting the other returned array?

Use reduce like so:
const arr = [{"Year":2019,"Title":"Asset Management Sample","Sum":1020000},{"Year":2019,"Title":"Monday test 2","Sum":2546658},{"Year":2020,"Title":"Asset Management Sample","Sum":1020000},{"Year":2020,"Title":"Monday test 2","Sum":3472000},{"Year":2021,"Title":"Asset Management Sample","Sum":1020000},{"Year":2021,"Title":"Monday test 2","Sum":2452000}];
const res = Object.values(arr.reduce((acc, { Year, Title, Sum }) => (acc[Year] = acc[Year] || { Year }, acc[Year][Title] = Sum, acc), {}));
console.log(res);
More verbose version:
const arr = [{"Year":2019,"Title":"Asset Management Sample","Sum":1020000},{"Year":2019,"Title":"Monday test 2","Sum":2546658},{"Year":2020,"Title":"Asset Management Sample","Sum":1020000},{"Year":2020,"Title":"Monday test 2","Sum":3472000},{"Year":2021,"Title":"Asset Management Sample","Sum":1020000},{"Year":2021,"Title":"Monday test 2","Sum":2452000}];
const res = Object.values(arr.reduce((acc, { Year, Title, Sum }) => {
acc[Year] = acc[Year] || { Year };
acc[Year][Title] = Sum;
return acc;
}, {}));
console.log(res);
.as-console-wrapper { max-height: 100% !important; top: auto; }
ES5 syntax:
var arr = [{"Year":2019,"Title":"Asset Management Sample","Sum":1020000},{"Year":2019,"Title":"Monday test 2","Sum":2546658},{"Year":2020,"Title":"Asset Management Sample","Sum":1020000},{"Year":2020,"Title":"Monday test 2","Sum":3472000},{"Year":2021,"Title":"Asset Management Sample","Sum":1020000},{"Year":2021,"Title":"Monday test 2","Sum":2452000}];
var res = arr.reduce(function(acc, curr) {
acc[curr.Year] = acc[curr.Year] || { Year: curr.Year };
acc[curr.Year][curr.Title] = curr.Sum;
return acc;
}, {});
res = Object.keys(res).map(function(key) {
return res[key];
});
console.log(res);
.as-console-wrapper { max-height: 100% !important; top: auto; }

Related

How to sort a collection of reservations

Model looks like so:
{
time: String,
date: Date,
user_id: String
},
return of end point get user reservations are like so
"reservations": [
{
"_id": "63e3bda0a2b3be512b44ba51",
"time": "10:40",
"date": "2023-02-06T00:00:00.000Z",
"user_id": "63d4657708205fda2de700f1"
},
{
"_id": "63e3bda2a2b3be512b44ba56",
"time": "11:00",
"date": "2023-02-06T00:00:00.000Z",
"user_id": "63d4657708205fda2de700f1"
},
{
"_id": "63e3c22bf83f5954d210eb56",
"time": "13:00",
"date": "2023-02-06T00:00:00.000Z",
"user_id": "63d4657708205fda2de700f1"
},
{
"_id": "63e3c224f83f5954d210eb48",
"time": "10:00",
"date": "2023-02-10T00:00:00.000Z",
"user_id": "63d4657708205fda2de700f1"
},
{
"_id": "63e3c228f83f5954d210eb4f",
"time": "10:00",
"date": "2023-02-16T00:00:00.000Z",
"user_id": "63d4657708205fda2de700f1"
}
]
How do i sort these reservations based on date and then time. So the earliest date with the earliest time slot, and this done inn all dates.
Can this be achieved with mongoose?
What i have tried:
const dates = reservations.map((res) => res.date.toISOString());
function onlyUnique(value: any, index: any, self: string | any[]) {
return self.indexOf(value) === index;
}
var distinctDates = dates.filter(onlyUnique);
First get all unique dates
for (let i = 0; i < distinctDates.length; i++) {
const date = new Date(distinctDates[i]);
let distinctReservations: { _id: any; time: number; date: Date; user_id: string }[] = [];
for (let j = 0; j < reservations.length; j++) {
const reservation = reservations[j];
if (reservation.date.toISOString() === date.toISOString()) {
distinctReservations.push({
_id: reservation.id,
time: hhMMToMinutes(reservation.time),
date: reservation.date,
user_id: reservation.user_id
});
}
}
const sortedByMinutes = distinctReservations.sort((a, b) => a.time - b.time);
sortedReservationsSlotToMinutes.push(sortedByMinutes);
}
const flated = sortedReservationsSlotToMinutes.flat(2);
const sortedReservations = flated.map((res) => {
let timeSlot = {
hour: (res.time / 60).toFixed(),
minute: ''
};
const minuteModule = res.time % 60;
if (minuteModule) {
timeSlot.minute = minuteModule.toString();
} else {
timeSlot.minute = '00';
}
return {
_id: res._id,
time: timeSlot.hour + ':' + timeSlot.minute,
date: res.date,
user_id: res.user_id
};
});
return sortedReservations;
Then loop through all unique dates and find matching of reservations. Reservations is a param inn this function. Then convert their time to minutes, sort based on the smalest value, then push those reservations into an array. After that i then push all reservations sorted by minutes to an outer array then i flaten that array and return it.
Then i convert back the minutes to string.
You can construct a datetime using $dateFromParts and use the datetime for sorting.
db.reservations.aggregate([
{
"$addFields": {
"dateTime": {
"$dateFromParts": {
"year": {
$year: "$date"
},
"month": {
$month: "$date"
},
"day": {
$year: "$date"
},
"hour": {
$toInt: {
"$substrCP": [
"$time",
0,
2
]
}
},
"minute": {
$toInt: {
"$substrCP": [
"$time",
3,
2
]
}
}
}
}
}
},
{
$sort: {
dateTime: 1
}
}
])
Mongo Playground

Nested array issue in JavaScript

I have the following array
Array["MyArray",
{
"isLoaded":true,
"items":
[{
"id":"4",
"name":"ProductA",
"manufacturer":"BrandA",
"quantity":1,
"price":"25"
},{
"id":"1",
"name":"ProductB",
"manufacturer":"BrandB",
"quantity":5,
"price":"20"
}],
"coupons":null
}
]
I need to load product names and their quantity from the array.
const result = [key, value].map((item) => `${item.name} x ${item.quantity}`);
Here's one possible way to achieve the desired result:
const getProductsAndQuantity = ([k , v] = arr) => (
v.items.map(it => `${it.name} x ${it.quantity}`)
);
How to use it within the context of the question?
localforage.iterate(function(value, key, iterationNumber) {
console.log([key, value]);
const val2 = JSON.parse(value);
if (val2 && val2.items && val2.items.length > 0) {
console.log(val2.items.map(it => `${it.name} x ${it.quantity}`).join(', '))
};
});
How it works?
Among the parameters listed in the question ie, value, key, iterationNumber, only value is required.
The above method accepts the key-value pair as an array (of 2 elements) closely matching the console.log([key, value]); in the question
It uses only v (which is an object). On v, it accesses the prop named items and this items is an Array.
Next, .map is used to iterate through the Array and return each product's name and quantity in the desired/expected format.
Test it out on code-snippet:
const arr = [
"MyArray",
{
"isLoaded": true,
"items": [{
"id": "4",
"name": "ProductA",
"manufacturer": "BrandA",
"quantity": 1,
"price": "25"
}, {
"id": "1",
"name": "ProductB",
"manufacturer": "BrandB",
"quantity": 5,
"price": "20"
}],
"coupons": null
}
];
const getProductsAndQuantity = ([k, v] = arr) => (
v.items.map(
it => `${it.name} x ${it.quantity}`
)
);
console.log(getProductsAndQuantity());
I understood. You should learn about array methods such as map, filter, reduce. Here you go...
const items = [{
"id":"4",
"name":"ProductA",
"manufacturer":"BrandA",
"quantity":1,
"price":"25"
},{
"id":"1",
"name":"ProductB",
"manufacturer":"BrandB",
"quantity":5,
"price":"20"
}];
const result = items.map((item) => `${item.name} x ${item.quantity}`);
console.log(result);
I think I understand the question to say that the input is an array of objects, each containing an array of items. The key is that a nested array requires a nested loop. So, we iterate the objects and their internal items (see the lines commented //outer loop and // inner loop below)
Also, half-guessing from the context, it looks like the that the OP aims to assemble a sort of invoice for each object. First a demo of that, (and see below for the version simplified to exactly what the OP asks)...
const addInvoice = obj => {
let total = 0;
// inner loop
obj.invoice = obj.items.map(i => {
let subtotal = i.quantity * i.price;
total += subtotal
return `name: ${i.name}, qty: ${i.quantity}, unit price: ${i.price}, subtotal: ${subtotal}`
});
obj.invoice.push(`invoice total: ${total}`);
}
const objects = [{
"isLoaded": true,
"items": [{
"id": "4",
"name": "ProductA",
"manufacturer": "BrandA",
"quantity": 1,
"price": "25"
}, {
"id": "1",
"name": "ProductB",
"manufacturer": "BrandB",
"quantity": 5,
"price": "20"
}],
"coupons": null
}]
// outer loop
objects.forEach(addInvoice);
console.log(objects);
If my guess about the goal went to far, just remove the unit price, subtotal and total lines from the invoice function...
const objects = [{
"isLoaded": true,
"items": [{
"id": "4",
"name": "ProductA",
"manufacturer": "BrandA",
"quantity": 1,
"price": "25"
}, {
"id": "1",
"name": "ProductB",
"manufacturer": "BrandB",
"quantity": 5,
"price": "20"
}],
"coupons": null
}]
const summaryString = obj => {
return obj.items.map(i => `${i.name}, ${i.quantity}`);
}
const strings = objects.map(summaryString);
console.log(strings);

Wrap Properties of one Object to another - JavaScript

May I know if using reduce I can achieve the following where the properties of activatedItems and quarterItems are wrapped in one object i.e., modules.
{
"isExternalVisitor": false,
"modules": [
{
"moduleId": "e569da0e-44e6-4f75-96c4-bdd888678abd",
"code": "NEWQ2/SITENAME/2021-Q3-1",
"siteId": "10babdbe-5346-43e8-932a-4c7ae54dcb1b",
"activatedId": "2e03c658-3bbd-4332-bb1b-14fe56c7e753"
},
{
"moduleId": "588905b4-2c1d-49bf-a71f-84210405bc94",
"code": "NEWQ1/SITENAME/2021-Q1-2",
"siteId": "10babdbe-5346-43e8-932a-4c7ae54dcb1b",
"activatedId": "6c1691d2-7c37-4888-a446-9219fa9b9014"
}
],
"activatedItems": [
{
"activatedId": "2e03c658-3bbd-4332-bb1b-14fe56c7e753",
"stQuarterId": "b36d7e23-15e5-4f97-b52e-65757de4b264"
},
{
"activatedId": "6c1691d2-7c37-4888-a446-9219fa9b9014",
"stQuarterId": "01000f98-6470-440a-a833-95b199ab1f7a"
}
],
"quarterItems": [
{
"id": "b36d7e23-15e5-4f97-b52e-65757de4b264",
"checklistId": "8b479656-8cde-4bff-9c51-d5eca369bc76",
"fullName": "dsad",
"year": "2021-01-01T00:00:00",
"quarter": "2021-Q3",
"versions": 1
},
{
"id": "01000f98-6470-440a-a833-95b199ab1f7a",
"checklistId": "039f2584-1ca5-4ee3-b46f-cdf1887af7f6",
"fullName": "NEWQ1",
"year": "2021-01-01T00:00:00",
"quarter": "2021-Q1",
"versions": 2
}
]
}
This is the expected result where only one object has got all the data.
{
"isExternalVisitor": false,
"modules": [
{
"moduleId": "e569da0e-44e6-4f75-96c4-bdd888678abd",
"code": "NEWQ2/SITENAME/2021-Q3-1",
"siteId": "10babdbe-5346-43e8-932a-4c7ae54dcb1b",
"activatedId": "2e03c658-3bbd-4332-bb1b-14fe56c7e753",
"stQuarterId": "b36d7e23-15e5-4f97-b52e-65757de4b264",
"checklistId": "8b479656-8cde-4bff-9c51-d5eca369bc76",
"fullName": "dsad",
"year": "2021-01-01T00:00:00",
"quarter": "2021-Q3",
"versions": 1
},
{
"moduleId": "588905b4-2c1d-49bf-a71f-84210405bc94",
"code": "NEWQ1/SITENAME/2021-Q1-2",
"siteId": "10babdbe-5346-43e8-932a-4c7ae54dcb1b",
"activatedId": "6c1691d2-7c37-4888-a446-9219fa9b9014",
"stQuarterId": "01000f98-6470-440a-a833-95b199ab1f7a",
"checklistId": "039f2584-1ca5-4ee3-b46f-cdf1887af7f6",
"fullName": "NEWQ1",
"year": "2021-01-01T00:00:00",
"quarter": "2021-Q1",
"versions": 2
}
]
}
I tried the following and was able to merge them in one array, but however, the end result is not the same as above. Your kind help will be appreciated.
let modules = arr.modules;
let activatedItems = arr.activatedItems;
let quarterItems = arr.quarterItems;
let finalArr = [];
modules.forEach(module => {
activatedItems.forEach(item =>{
if(item.activatedId == module.activatedId)
{
quarterItems.forEach(quaItem => {
if(quaItem.id == item.stQuarterId){
finalArr.push(module);
finalArr.push(item);
finalArr.push(quaItem);
}
})
}
})
})
it seems you're just joining the arrays on index. If that's the case, a simple map will do! Just map over modules and use the index of the map callback function to grab the corresponding object from the other arrays.
const obj={isExternalVisitor:!1,modules:[{moduleId:"e569da0e-44e6-4f75-96c4-bdd888678abd",code:"NEWQ2/SITENAME/2021-Q3-1",siteId:"10babdbe-5346-43e8-932a-4c7ae54dcb1b",activatedId:"2e03c658-3bbd-4332-bb1b-14fe56c7e753"},{moduleId:"588905b4-2c1d-49bf-a71f-84210405bc94",code:"NEWQ1/SITENAME/2021-Q1-2",siteId:"10babdbe-5346-43e8-932a-4c7ae54dcb1b",activatedId:"6c1691d2-7c37-4888-a446-9219fa9b9014"}],activatedItems:[{activatedId:"2e03c658-3bbd-4332-bb1b-14fe56c7e753",stQuarterId:"b36d7e23-15e5-4f97-b52e-65757de4b264"},{activatedId:"6c1691d2-7c37-4888-a446-9219fa9b9014",stQuarterId:"01000f98-6470-440a-a833-95b199ab1f7a"}],quarterItems:[{id:"b36d7e23-15e5-4f97-b52e-65757de4b264",checklistId:"8b479656-8cde-4bff-9c51-d5eca369bc76",fullName:"dsad",year:"2021-01-01T00:00:00",quarter:"2021-Q3",versions:1},{id:"01000f98-6470-440a-a833-95b199ab1f7a",checklistId:"039f2584-1ca5-4ee3-b46f-cdf1887af7f6",fullName:"NEWQ1",year:"2021-01-01T00:00:00",quarter:"2021-Q1",versions:2}]};
const result = {
isExternalId: obj.isExternalId
};
result.modules = obj.modules.map((el, i) => ({
...el,
...obj.activatedItems[i],
...obj.quarterItems[i]
}));
console.log(result);

how to use reduce with query on Dynamodb scan

I am learning DynamoDB and have difficulties understanding where to perform a reduction on data once a DynamoDB query has provided the results and where in the code it would go.
I would like to sum up the running_time_secs.
async function scanForResults () {
try {
var params = {
TableName: "Movies",
ProjectionExpression: "#yr, title, info.rating, info.running_time_secs, info.genres",
FilterExpression: "#yr between :start_yr and :end_yr",
ExpressionAttributeNames: {
"#yr": "year",
},
ExpressionAttributeValues: {
":start_yr": 1950,
":end_yr": 1985,
}
};
var result = await docClient.scan(params).promise()
console.log(JSON.stringify(result))
//const total = result.reduce((sum, result) => sum + result.info.running_time_secs, 0);
} catch (error) {
console.error(error);
}
}
scanForResults();
Thanks for any help.
EDITED
Maybe you can post the actual value of the result once you resolve it. It would be best to know the actual structure of the result value to better see how you should approach it. You can site the documentation for further reference. It is actually really helpful.
var result = [{
"title": "Piranha",
"year": 1978,
"info": {
"rating": 5.8,
"genres": ["Comedy", "Horror", "Sci-Fi"],
"running_time_secs": 5640
}
}]
var total = result.reduce((sum, result) => sum + result.info.running_time_secs, 0);
console.log(total);
var result2 = [{
"title": "Piranha",
"year": 1978,
"info": {
"rating": 5.8,
"genres": ["Comedy", "Horror", "Sci-Fi"],
"running_time_secs": 5640
}
},
{
"title": "Piranha2",
"year": 1980,
"info": {
"rating": 5.8,
"genres": ["Comedy", "Horror", "Sci-Fi"],
"running_time_secs": 5640
}
}
]
var total2 = result2.reduce((sum, result) => sum + result.info.running_time_secs, 0);
console.log(total2);
var resultObj = {
"title": "Piranha",
"year": 1978,
"info": {
"rating": 5.8,
"genres": ["Comedy", "Horror", "Sci-Fi"],
"running_time_secs": 5640
}
}
var totalObj = resultObj.reduce((sum, result) => sum + result.info.running_time_secs, 0);
console.log(totalObj);
I think base on the error you are receiving, result might not be an array. You can refer to the code snippet I posted. I used your code and just created the result array to mimic the result you get from the scan function. As you can see on the 3rd reduce function used on resultObj, I got the response error you got. reduce is an array method and using it to an object would result in such an error because object does not implement this method. Hence, I think that the result you are getting is not an array.

Reorder JSON based on date using Jquery/JS

Thanks ahead for your help!
I'm trying to reorder some objects so the newest ordered product would be first. So looking at the data below, the new order should be (from newest to oldest) product2, product3, and then product1.
{
"candyResponse": {
"product1": {
"displayName": "Bubble Gum",
"imageURL": "https://dummyimage.com/200x200/000/ffffff.png&text=prod1?$146$",
"orderDate": {
"time": "11/03/2018"
}
},
"product2": {
"displayName": "Chocolate",
"imageURL": "https://dummyimage.com/200x200/000/ffffff.png&text=prod2?$146$",
"orderDate": {
"time": "03/05/2015"
}
},
"product3": {
"displayName": "Mints",
"imageURL": "https://dummyimage.com/200x200/000/ffffff.png&text=prod3?$146$",
"orderDate": {
"time": "09/20/2017"
}
}
}
}
I tweaked the code from Sorting an array of JavaScript objects but I was not successful. Tried three ways...
candyResponse.sort(function(a, b) {
return parseFloat(a.time) - parseFloat(b.time);
});
candyResponse.sort(function(a, b) {
return parseFloat(a.orderDate) - parseFloat(b.orderDate);
});
candyResponse.sort(function(a, b) {
return parseFloat(a.orderDate.time) - parseFloat(b.orderDate.time);
});
Thanks again for your help!
candyResponse is an object, not an array - objects' property names are not reliably ordered, per the spec, so even if you did create a new object with the properties in the desired insertion order, it wouldn't be something to rely on.
Sort an array instead:
const candyResponse = {
"product1": {
"displayName": "Bubble Gum",
"imageURL": "https://dummyimage.com/200x200/000/ffffff.png&text=prod1?$146$",
"orderDate": {
"time": "11/03/2018"
}
},
"product2": {
"displayName": "Chocolate",
"imageURL": "https://dummyimage.com/200x200/000/ffffff.png&text=prod2?$146$",
"orderDate": {
"time": "03/05/2015"
}
},
"product3": {
"displayName": "Mints",
"imageURL": "https://dummyimage.com/200x200/000/ffffff.png&text=prod3?$146$",
"orderDate": {
"time": "09/20/2017"
}
}
};
const getTime = ([_, product]) => {
return new Date(product.orderDate.time);
};
const sortedCandyArr = Object.entries(candyResponse)
.sort((a, b) => getTime(b) - getTime(a));
console.log(sortedCandyArr);
Well, you don't have an array of javascript objects, you just have a javascript object. That being said, you could do:
var data = {
"candyResponse": {
"product1": {
"displayName": "Bubble Gum",
"imageURL": "https://dummyimage.com/200x200/000/ffffff.png&text=prod1?$146$",
"orderDate": {
"time": "11/03/2018"
}
},
"product2": {
"displayName": "Chocolate",
"imageURL": "https://dummyimage.com/200x200/000/ffffff.png&text=prod2?$146$",
"orderDate": {
"time": "03/05/2015"
}
},
"product3": {
"displayName": "Mints",
"imageURL": "https://dummyimage.com/200x200/000/ffffff.png&text=prod3?$146$",
"orderDate": {
"time": "09/20/2017"
}
}
}
}
var sorted = Object.keys(data.candyResponse)
.sort((a, b) =>
new Date(data.candyResponse[a].orderDate.time).getTime() -
new Date(data.candyResponse[b].orderDate.time).getTime());
data.candyResponse = sorted.reduce((carry, current) => { carry[current] = data.candyResponse[current]; return carry; }, {});
console.log(data)

Categories

Resources