Pull data from sub object within array - javascript

I can't see what I'm doing wrong here but I'm getting "undefined" back in my console.
Hopefully you can see in the snippet I am passing in some JSON data. This effectively 2 stores worth of data and against each store there are a few transactions. I can pull back the top level data but I'm struggling to pull back data from the transaction line level.
Its whenever I try to reference something from within my transaction lines. Can anyone point me in the right direction as to how I'm referencing that part of my array?
Many thanks
///Dummy JSON Data Stringified and put in the top /////////
const inputData= "[{\r\n\t\t\"transaction\": 1,\r\n\t\t\"store\": 1,\r\n\t\t\"transactionLines\": [{\r\n\t\t\t\t\"transactionId\": 1,\r\n\t\t\t\t\"lineId\": 3,\r\n\t\t\t\t\"lineValue\": 25\r\n\t\t\t},\r\n\r\n\t\t\t{\r\n\t\t\t\t\"transactionId\": 1,\r\n\t\t\t\t\"lineId\": 2,\r\n\t\t\t\t\"lineValue\": 50\r\n\t\t\t},\r\n\t\t\t{\r\n\t\t\t\t\"transactionId\": 1,\r\n\t\t\t\t\"lineId\": 1,\r\n\t\t\t\t\"lineValue\": 100\r\n\t\t\t}\r\n\t\t]\r\n\t},\r\n\t{\r\n\t\t\"transaction\": 2,\r\n\t\t\"store\": 2,\r\n\t\t\"transactionLines\": [{\r\n\t\t\t\t\"transactionId\": 1,\r\n\t\t\t\t\"lineId\": 2,\r\n\t\t\t\t\"lineValue\": 50\r\n\t\t\t},\r\n\t\t\t{\r\n\t\t\t\t\"transactionId\": 1,\r\n\t\t\t\t\"lineId\": 1,\r\n\t\t\t\t\"lineValue\": 100\r\n\t\t\t}\r\n\t\t]\r\n\t}\r\n]"
const input = JSON.parse(inputData);
var total = 0;
////// First "For Loop" goes through input data /////
////// and lists transactions ///////////////////////
for(let i=0;i<input.length;i++){
console.log(input[i].transaction);
///////// 2nd "For Loop" is inside the transaction loop. ////////
///////// This goes through transaction data from the above loop /
///////// and lists transactions ///////////////////////////////
for(let j=0;j<input[i].transactionLines.length;j++){
///////// Increase the total by adding the line value to the /////
///////// existing total ////////////////////////////////////////
total = total+input[i].lineValue
console.log(input[i].transactionLines.lineId);
console.log("Transaction ID = "+input[i].transaction+" loop x "+j+": New Total = "+input[i].transactionLines.transactionId);
}
}
<div>
<h1>
Sample Json Data Shown Below
</h1>
<h2>
Check console for outputs
</h2>
</div>
<xmp>
[{
"transaction": 1,
"store": 1,
"transactionLines": [{
"transactionId": 1,
"lineId": 3,
"lineValue": 25
},
{
"transactionId": 1,
"lineId": 2,
"lineValue": 50
},
{
"transactionId": 1,
"lineId": 1,
"lineValue": 100
}
]
},
{
"transaction": 2,
"store": 2,
"transactionLines": [{
"transactionId": 1,
"lineId": 2,
"lineValue": 50
},
{
"transactionId": 1,
"lineId": 1,
"lineValue": 100
}
]
}
]
</xmp>

You forgot to use j variable
///Dummy JSON Data Stringified and put in the top /////////
const inputData = "[{\r\n\t\t\"transaction\": 1,\r\n\t\t\"store\": 1,\r\n\t\t\"transactionLines\": [{\r\n\t\t\t\t\"transactionId\": 1,\r\n\t\t\t\t\"lineId\": 3,\r\n\t\t\t\t\"lineValue\": 25\r\n\t\t\t},\r\n\r\n\t\t\t{\r\n\t\t\t\t\"transactionId\": 1,\r\n\t\t\t\t\"lineId\": 2,\r\n\t\t\t\t\"lineValue\": 50\r\n\t\t\t},\r\n\t\t\t{\r\n\t\t\t\t\"transactionId\": 1,\r\n\t\t\t\t\"lineId\": 1,\r\n\t\t\t\t\"lineValue\": 100\r\n\t\t\t}\r\n\t\t]\r\n\t},\r\n\t{\r\n\t\t\"transaction\": 2,\r\n\t\t\"store\": 2,\r\n\t\t\"transactionLines\": [{\r\n\t\t\t\t\"transactionId\": 1,\r\n\t\t\t\t\"lineId\": 2,\r\n\t\t\t\t\"lineValue\": 50\r\n\t\t\t},\r\n\t\t\t{\r\n\t\t\t\t\"transactionId\": 1,\r\n\t\t\t\t\"lineId\": 1,\r\n\t\t\t\t\"lineValue\": 100\r\n\t\t\t}\r\n\t\t]\r\n\t}\r\n]"
const input = JSON.parse(inputData);
var total = 0;
////// First "For Loop" goes through input data /////
////// and lists transactions ///////////////////////
for (let i = 0; i < input.length; i++) {
console.log(input[i].transaction);
///////// 2nd "For Loop" is inside the transaction loop. ////////
///////// This goes through transaction data from the above loop /
///////// and lists transactions ///////////////////////////////
for (let j = 0; j < input[i].transactionLines.length; j++) {
///////// Increase the total by adding the line value to the /////
///////// existing total ////////////////////////////////////////
total = total + input[i].lineValue
console.log(input[i].transactionLines[j].lineId);
console.log("Transaction ID = " + input[i].transaction + " loop x " + j + ": New Total = " + input[i].transactionLines[j].transactionId);
}
}
<div>
<h1>
Sample Json Data Shown Below
</h1>
<h2>
Check console for outputs
</h2>
</div>
<xmp>
[{ "transaction": 1, "store": 1, "transactionLines": [{ "transactionId": 1, "lineId": 3, "lineValue": 25 }, { "transactionId": 1, "lineId": 2, "lineValue": 50 }, { "transactionId": 1, "lineId": 1, "lineValue": 100 } ] }, { "transaction": 2, "store": 2,
"transactionLines": [{ "transactionId": 1, "lineId": 2, "lineValue": 50 }, { "transactionId": 1, "lineId": 1, "lineValue": 100 } ] } ]
</xmp>

Related

How to sum multiplication values from objects in an array?

if i have an array that looks like this :
"orderItems": [
{
"description": "Test",
"identifier": "Test identifier",
"priceCent": 1,
"lengthIn": 10,
"widthIn": 5,
"heightIn": 10,
"weightLbs": 3,
"quantity": 2
},
{
"description": "Test-2",
"identifier": "Test identifier",
"priceCent": 1,
"lengthIn": 10,
"widthIn": 5,
"heightIn": 10,
"weightLbs": 4,
"quantity": 3
}
]
How can I multiply weightLbs and quantity and sum those within the objects?
For example:
3 * 2 = 6
4 * 3 = 12
and result total I want is = 18
This is what I have so far, but this only adds weightLbs
return delivery.order.orderItems.reduce((prev, curr) => {
return prev + (curr.totalWeightLbs || 0);
}, 0);
orderItems.reduce((sum, currentItem) => {
return sum + (currentItem.weightLbs * currentItem.quantity);
}, 0);
this will multiply the values and sum them in the reduce accumulator
const dummyArray = [
{
"description": "Test",
"identifier": "Test identifier",
"priceCent": 1,
"lengthIn": 10,
"widthIn": 5,
"heightIn": 10,
"weightLbs": 3,
"quantity": 2
},
{
"description": "Test-2",
"identifier": "Test identifier",
"priceCent": 1,
"lengthIn": 10,
"widthIn": 5,
"heightIn": 10,
"weightLbs": 4,
"quantity": 3
}
];
let sum = 0;
for( i = 0; i < dummyArray.length; i++)
sum += dummyArray[i].weightLbs * dummyArray[i].quantity
console.log(sum)
this might work

Ordering an array of object literals

I have this array of object.
I am trying to rearrange them by given order or sequence.
E.g if I say oil should come on order = 1 then the object of oil should come on top and if I say petrol should be order = 3 then the object of petrol should come on 3rd place.
Here is something I have tried so far but I am not achieving the correct result:
Also here is a working jsfiddle:
https://jsfiddle.net/voqgs7j8/
var utilities = {
"petrol": {
"title": "Petrol",
"price": 10
},
"oil": {
"title": "Oil",
"price": 12
},
"sugar": {
"title": "Sugar",
"price": 14
},
"flour": {
"title": "Flour",
"price": 65
} ,
"apple": {
"title": "apple",
"price": 20
} ,
"banana": {
"title": "banana",
"price": 30
} ,
"orange": {
"title": "orange",
"price": 19
}
};
//var getUtilityUserPreferences = {utilityOrders: []};// to test empty DB values
var getUtilityUserPreferences = {utilityOrders: [{"utility": "petrol", "order": 5}, {"utility": "oil", "order": 1}, {"utility": "flour", "order": 2}]};
var response = utilities;// by default it holds all same ordered values
if(getUtilityUserPreferences && getUtilityUserPreferences.utilityOrders && getUtilityUserPreferences.utilityOrders.length){
// OH we found user defined orders, so calculation starts with empty response
var response = {};
var resPointer = 1;// holds current index of final response, where the obj will be pushed
var dbArrIndex = 0;// current db arr index that is waiting for its turn, to be pushed
// loop through all values and keep pushing in final response unless some DB values comes and get pushed first
for(var key in utilities){
if(dbArrIndex < getUtilityUserPreferences.utilityOrders.length){// if db arr is not finished yet, otherwise we are done with db array
// trying to check if its time for DB values to be pushed, otherwise all of above loop will be pushed
var matching = true;
while(matching && dbArrIndex < getUtilityUserPreferences.utilityOrders.length){// loop can also finish db arr, so validating again
if(getUtilityUserPreferences.utilityOrders[dbArrIndex].order == resPointer){
response[getUtilityUserPreferences.utilityOrders[dbArrIndex].utility] = utilities[getUtilityUserPreferences.utilityOrders[dbArrIndex].utility];resPointer++;
delete utilities[getUtilityUserPreferences.utilityOrders[dbArrIndex].utility];
matching = true;
dbArrIndex++;
}
else{
matching = false;
}
}
}
if(utilities[key]){// could be null by upper if
response[key] = utilities[key];resPointer++;
}
}
}
//DONE!!!!!
for(var key in response){
//console.log(key);
}
console.log(response);
return response;

How to find data in for every day of week in mongoose node js

Query
const weekGraph = await tmUserSubscriptions.aggregate([
{
$match:{$and:[{subscriptionId: mongoose.Types.ObjectId(subscriptionId)},
{createdAt:{$gte:moment().startOf('isoweek').toDate(),
$lt:moment().endOf('isoweek').toDate()}}
]}
},
{"$project":{
"_id:":1,
"createdAt":{"$dayOfWeek":"$createdAt"},
"subscriptionId":1,
}},
{"$group":{
"_id":"$createdAt",
"count":{$sum:1},
}}
])
Result i get
"data": [
{
"_id": 7,
"count": 1
},
{
"_id": 5,
"count": 2
},
{
"_id": 6,
"count": 1
}
]
expected Result
"data": [
{
"_id": 7,
"count": 1
},
{
"_id": 6,
"count": 2
},
{
"_id": 5,
"count": 1
},
{
"_id": 4,
"count": 0
},{
"_id": 3,
"count": 0
},{
"_id": 2,
"count": 0
}{
"_id": 1,
"count": 0
}
]
So here i want to achieve all data of current week day by day, in my current query if there is no data any of week day then it will not return that day, but as per my expected result i want all day of week data, if there is no data for any of week day then it will return 0, so i want all 7 days data,
here _id is represent day of week
Mongoose/MongoDB will only return the aggregate if the key exists. Otherwise, it will not return you the data (less data to transfer through the connection is always faster). Therefore, you will need to provide your own defaults if the aggregate does not have data for you.
var results = [{ _id: 1, count: 1 }] // assumed from your response
var hasResult = []
for (var result of results) {
hasResult.push(result._id)
}
for (var i = 1; i <= 7; i++) {
if (!hasResult.includes(i)) {
results.push({ _id: i, count: 0 })
}
}
console.log(results)

JavaScript: Creating 2 dimensional array of objects based on condition

I'm working on a project that involves two dimensional arrays of objects. I've been working to try to figure out this answer for a while now, and I have some ideas of how to solve it, but I'm a bit stumped.
Let's assume there are animal shelters in City A and that each can hold 50 animals. Animals are coming in from different parts of the state, but the amount of animals from one place can never be more than 50. Here's an example of the animals coming in.
let animal_shelter_capacity =< 50;
let array 1 = [
{ "region": "NE", quantity: 25 },
{ "region": "NW", quantity: 21 },
{ "region": "SE", quantity: 43 },
{ "region": "SW", quantity: 18 },
{ "region": "Central", quantity: 20}
]
In this example, the animals from NE (25) and NW (21) would go to one shelter (46 animals in total), the animals from SE (43) would go to another shelter (43 animals in total), and the animals from SW (18) and Central (20) would go to a third shelter (38 animals in total). The number of animals in one shelter can never be greater than 50.
So, I need to produce an array that looks like this:
let array2 = [
[ { "region": "NE", quantity: 25 }, { "region": "NW", quantity: 21 }],
[ { "region": "SE", quantity: 43 } ],
[ { "region": "SW", quantity: 18 }, { "region": "Central", quantity: 20} ]
]
I'm able to loop through array1 using forEach, but when it comes to adding until a certain value is reached, then creating a new array of arrays, I'm a little stumped on how to proceed to do this.
Here's what I have so far:
let array2 = [] //instantiate array
array1.forEach(function(element, index, array)
{
let sum = 0;
let capacity = 50;
for (let j = 0; j < array1.length; j++)
{
sum += array1[j].quantity;
if (sum >= capacity)
{
//create the new array consisting of the regions, push it into the larger array2
}
}
})
I'm not sure how to continue doing this. I know I need to do the following:
1. find a way to cut off the addition sequence once the quantity reaches 50
2. reset the sequence
3. form the new arrays and push them into a larger array
Can anyone provide any advice on how to proceed?
Try this. Loop through shelters, if it can fit, add it to the current shelter list. If not, save the current shelter roster and start a new one. After the loop, make sure to save the current roster being written
const locations = [{
"region": "NE",
"quantity": 25
},
{
"region": "NW",
"quantity": 21
},
{
"region": "SE",
"quantity": 43
},
{
"region": "SW",
"quantity": 18
},
{
"region": "Central",
"quantity": 20
}
]
const shelterRoster = [];
const capacity = 50;
let count = 0;
for (let location of locations) {
let shelter = shelterRoster[shelterRoster.length - 1];
if (!shelter || count + location.quantity > capacity) {
shelterRoster.push([location]);
count = 0;
} else {
shelter.push(location);
}
count += location.quantity
}
console.log(shelterRoster);
You can approach this with reduce(), using a custom object as the initial accumulator. When the reduce finish, you will need to do an extra line of code for get your final result.
const animal_shelter_capacity = 50;
const array1 = [
{"region": "NE", quantity: 25},
{"region": "NW", quantity: 21},
{"region": "SE", quantity: 43},
{"region": "SW", quantity: 18},
{"region": "Central", quantity: 20}
];
let obj = array1.reduce((res, curr) =>
{
let test = (curr.quantity + res.c >= animal_shelter_capacity);
return {
r: test ? [...res.r, res.a] : res.r,
c: test ? curr.quantity : res.c + curr.quantity,
a: test ? [curr] : [...res.a, curr]
};
},{r:[], c:0, a:[]});
let newArr = [...obj.r, obj.a];
console.log(newArr);
On the previous code, the accumulated object have the next keys:
r: The array of shelters generated progressively.
c: The counter of animals of the current shelter (see next).
a: The current shelter of animals.
When the reduce finish, the last shelter (that on the property a) will not be on the array of shelters. So, we have to put it manually (this is what the extra line does).
The first point I've come up with, is you need to sort input data first. because your given input ( as asked in the question ) is not the only possible way of having data.
You can have some data like:
let array1 = [
{ "region": "NE", quantity: 25 },
{ "region": "NW", quantity: 21 },
{ "region": "Central", quantity: 20 },
{ "region": "SE", quantity: 43 },
{ "region": "SW", quantity: 18 },
]
and in this example, we should have pushed central and SW together, but not sorting the input at first place will result central and SW in different arrays.
So, conclusion. I think this is gonna work:
var make = function( arr ) {
var res = [],
currentArr = [];
arr.forEach( v => {
sum += v.quantity;
if ( sum <= capacity ) {
currentArr.push( v );
} else {
res.push( currentArr );
currentArr = [ v ];
sum = v.quantity;
}
});
res.push( currentArr );
return res;
},
array1 = [
{ "region": "NE", quantity: 25 },
{ "region": "NW", quantity: 21 },
{ "region": "Central", quantity: 20 },
{ "region": "SE", quantity: 43 },
{ "region": "SW", quantity: 18 }
],
sum = 0,
result,
capacity = 50;
array1.sort( ( a, b ) => {
return a.quantity - b.quantity;
});
console.log( array1 );
result = make( array1 );
console.log( result );

Grouping multiple documents in mongodb

I am trying to create a golf leaderboard based on multiple rounds, which means that a player can have played 2 rounds with the same matchid. It is pretty simple if there is just one round, I do it like this:
db.roundScores.find( { "matchId": matchId } ).sort({"data.scoreTotals.toPar": 1});
But, if a match have more than one round, I am a little in the dark on how i group each player, add the scores for the rounds and then sort them?
I am walking down this way, but not sure if this is the right way?
var allRounds = db.rounds.find( { "matchId": matchId } );
var playerScores = [];
while( allRounds.hasNext() ) {
var thisRound = allRounds.next();
var allScores = db.roundScores.find( { "roundId": thisRound._id.$oid } );
var i = 0;
while( allScores.hasNext() ) {
var thisScore = allScores.next();
if(i > 0){
// Should be updating the playerScores array finding the object for the player, But how???
} else {
// Creating a new object and adding it to the playerScores array //
playerScores.push({
"id": thisScore.playerId,
"toPar": thisScore.scoretotals.toPar,
"points": thisScore.scoretotals.points
});
}
i++;
}
}
I really hope that someone can guide me in the right direction on this.
Thanks in advance :-)
------------ EDIT -----------
Here is examples on the documents
{"roundId": "8745362738", "playerId": "12653426518", "toPar": 3, "points": 27}
{"roundId": "8745362738", "playerId": "54354245566", "toPar": -1, "points": 31}
{"roundId": "7635452678", "playerId": "12653426518", "toPar": 1, "points": 29}
{"roundId": "7635452678", "playerId": "54354245566", "toPar": 2, "points": 23}
The result should be:
1 playerId 54354245566 toPar 1 points 10
2 playerId 12653426518 toPar 4 points 2
Here is something to get you going:
db.roundScores.aggregate([{
$group: {
_id: "$playerId", // group by playerId
toPar: { $sum: "$toPar" }, // sum up all scores
points: { $sum: { $max: [ 0, { $subtract: [ "$points", 25 ] } ] } }, // sum up all points above 25
}
}, {
$sort: { "toPar": 1 } // sort by toPar ascending
}])
You can go with MongoDB aggregation for this. A sample code below
db.roundScores.aggregate({
$group: {
_id: "$playerId",
toPar: { $sum: "$toPar" },
{$sort:{"toPar":1}}
}
})
This will work

Categories

Resources