Related
I try to update a sport tournament pool table in a MongoDB collection. Pool tables data look that way :
{
id: 1,
pool: 'A',
teams: [
{name:'New-Zealand', wins: 4, draws: 0, losses: 0, PointsFor: 143, PointsAgainst: 35, DIFF: 0},
{name:'France', wins: 3, draws: 0, losses: 1, PointsFor: 129, PointsAgainst: 41, DIFF: 0},
{name:'Italy', wins: 2, draws: 0, losses: 2, PointsFor: 88, PointsAgainst: 75, DIFF: 0},
{name:'Uruguay', wins: 0, draws: 1, losses: 3, PointsFor: 50, PointsAgainst: 102, DIFF: 0},
{name:'Namibia', wins: 0, draws: 1, losses: 3, PointsFor: 53, PointsAgainst: 113, DIFF: 0}
]
},
{
id: 2,
pool: 'B',
teams: [
{name:'South-Africa', wins: 3, draws: 1, losses: 0, PointsFor: 132, PointsAgainst: 32, DIFF: 0},
{name:'Ireland', wins: 3, draws: 1, losses: 0, PointsFor: 126, PointsAgainst: 35, DIFF: 0},
{name:'Scotland', wins: 2, draws: 0, losses: 2, PointsFor: 95, PointsAgainst: 69, DIFF: 0},
{name:'Tonga', wins: 1, draws: 0, losses: 3, PointsFor: 66, PointsAgainst: 91, DIFF: 0},
{name:'Romania', wins: 0, draws: 0, losses: 4, PointsFor: 30, PointsAgainst: 110, DIFF: 0}
]
}
];
I have written the functions that increment wins, draws, losses, PointsFor and PointsAgainst according to some forecasts stored in an other collection. Now, I'm trying to change DIFF properties so that for each object in teams array, DIFF = PointsFor - PointsAgainst.
I'm new to MongoDB and I thought about using the '$subtract' method but I don't understand how aggregation operations work.
Thanks in advance for your assistance.
You can do it via below update/aggregation operation (4.2+):
db.collection.update({},
[
{
"$addFields": {
"teams": {
"$map": {
"input": "$teams",
"as": "t",
"in": {
"$mergeObjects": [
"$$t",
{
DIFF: {
"$subtract": [
"$$t.PointsFor",
"$$t.PointsAgainst"
]
}
}
]
}
}
}
}
}
],
{
multi: true
})
Explained:
Use $addFields/$map/$mergeObjects/$subtract to walk over all teams array elements and update the DIFF field.
Use {multi:true} update option to update all documents in your collection
Playground
(14) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]
0: {itemId: 'F4', itemRate: 20, Amount: 20, itemName: 'Kesar pista', itemQuantity: 1}
1: {itemName: 'Vegetable manchuri', itemRate: 60, itemId: 'G5', Amount: 120, itemQuantity: 2}
2: {itemRate: 50, Amount: 50, itemQuantity: 1, itemId: 'C10', itemName: 'Dry fruit '}
3: {itemId: 'C3', itemRate: 40, itemQuantity: 1, Amount: 40, itemName: 'Butter scotch'}
4: {itemName: 'Panner sandwich + milk shake', Amount: 90, itemId: 'CS4', itemRate: 90, itemQuantity: 1}
5: {itemQuantity: 1, itemId: 'B5', itemRate: 70, Amount: 70, itemName: 'Panner burger'}
6: {itemId: 'C10', itemQuantity: 1, Amount: 50, itemName: 'Dry fruit ', itemRate: 50}
7: {itemQuantity: 2, itemName: 'American nuts', Amount: 100, itemRate: 50, itemId: 'C8'}
8: {itemName: 'Mango ', Amount: 50, itemQuantity: 1, itemId: 'C7', itemRate: 50}
9: {Amount: 40, itemId: 'C6', itemQuantity: 1, itemName: 'Choclate ', itemRate: 40}
10: {itemRate: 40, itemId: 'C3', itemQuantity: 1, Amount: 40, itemName: 'Butter scotch'}
11: {itemRate: 45, itemId: 'B1', itemName: 'Veg burger', Amount: 45, itemQuantity: 1}
12: {itemName: 'Veg cheese', Amount: 55, itemId: 'B2', itemQuantity: 1, itemRate: 55}
13: {itemName: 'Vanila', itemQuantity: 1, itemId: 'C1', Amount: 30, itemRate: 30}
length: 14
[[Prototype]]: Array(0)
I have a array. In the array there are 2 [id] values that are the same. I want to add the quantity,rate of these elements and merge the elements where the [id] are the same using javascript. I had tried following method but it shows wrong value.
let result = Object.values(this.orderDetail.reduce((c, {itemId,itemRate,itemQuantity,itemName}) => {
c[itemId] = c[itemId] || {itemId,itemRate,itemQuantity,itemName: 0};
c[itemId].itemRate += itemRate;
c[itemId].itemQuantity += itemQuantity;
c[itemId].itemName = itemName;
return c;
}, {}));
result
The issue is with the first line in the accumulator.
c[itemId] = c[itemId] || {itemId,itemRate,itemQuantity,itemName: 0};
You should assign the initial values here. This should be as below
c[itemId] = c[itemId] || { itemId, itemRate: 0, itemQuantity: 0, itemName: '', Amount: 0 };
Or else, you will be adding the first value twice to the accumulator.
Working Fiddle
const data = [{ itemId: 'F4', itemRate: 20, Amount: 20, itemName: 'Kesar pista', itemQuantity: 1 },
{ itemId: 'G5', itemName: 'Vegetable manchuri', itemRate: 60, Amount: 120, itemQuantity: 2 },
{ itemId: 'C10', itemRate: 50, Amount: 50, itemQuantity: 1, itemName: 'Dry fruit ' },
{ itemId: 'C3', itemRate: 40, itemQuantity: 1, Amount: 40, itemName: 'Butter scotch' },
{ itemId: 'CS4', itemName: 'Panner sandwich + milk shake', Amount: 90, itemRate: 90, itemQuantity: 1 },
{ itemId: 'B5', itemQuantity: 1, itemRate: 70, Amount: 70, itemName: 'Panner burger' },
{ itemId: 'C10', itemQuantity: 1, Amount: 50, itemName: 'Dry fruit ', itemRate: 50 },
{ itemId: 'C8', itemQuantity: 2, itemName: 'American nuts', Amount: 100, itemRate: 50 },
{ itemId: 'C7', itemName: 'Mango ', Amount: 50, itemQuantity: 1, itemRate: 50 },
{ itemId: 'C6', Amount: 40, itemQuantity: 1, itemName: 'Choclate ', itemRate: 40 },
{ itemId: 'C3', itemRate: 40, itemQuantity: 1, Amount: 40, itemName: 'Butter scotch' },
{ itemId: 'B1', itemRate: 45, itemName: 'Veg burger', Amount: 45, itemQuantity: 1 },
{ itemId: 'B2', itemName: 'Veg cheese', Amount: 55, itemQuantity: 1, itemRate: 55 },
{ itemId: 'C1', itemName: 'Vanila', itemQuantity: 1, Amount: 30, itemRate: 30 },
];
let result = Object.values(data.reduce((c, { itemId, itemRate, itemQuantity, itemName, Amount }) => {
const temp = { itemId, itemRate: 0, itemQuantity: 0, itemName: '', Amount: 0 };
c[itemId] = c[itemId] || temp;
c[itemId].itemRate += itemRate;
c[itemId].itemQuantity += itemQuantity;
c[itemId].itemName = itemName;
c[itemId].Amount += Amount;
return c;
}, {}));
console.log(result);
As I looked into the result, there is one extra time all values are passing into it. I guess you should try passing default values zero or an empty string to it.
I am struggling with a rather complicated operation on an array of objects. First this is a sample array:
[
{id: 11, item: 132, lineNum: 4, linePosition: 5}
{id: 2, item: 124, lineNum: 0, linePosition: 2}
{id: 9, item: 130, lineNum: 0, linePosition: 5}
{id: 12, item: 133, lineNum: 1, linePosition: 3}
{id: 15, item: 136, lineNum: 3, linePosition: 2}
{id: 13, item: 134, lineNum: 0, linePosition: 4}
{id: 10, item: 131, lineNum: 2, linePosition: 1}
{id: 8, item: 129, lineNum: 3, linePosition: 3}
{id: 1, item: 123, lineNum: 0, linePosition: 5}
{id: 3, item: 125, lineNum: 1, linePosition: 7}
{id: 5, item: 127, lineNum: 0, linePosition: 9}
{id: 7, item: 128, lineNum: 1, linePosition: 2}
{id: 4, item: 126, lineNum: 0, linePosition: 4}
{id: 14, item: 135, lineNum: 3, linePosition: 9}
]
So I would like to do the following operations in order and as efficiently as possible. Sort the array by lineNum then by item both ascending. Then I would like to modify each object where lineNum === 0 to make the linePosition an incrementing number starting at 0. So the first matching object would have linePosition of 0, next would be 1, then 2, etc.
Resulting array would look like this:
[
{id: 1, item: 123, lineNum: 0, linePosition: 0}
{id: 2, item: 124, lineNum: 0, linePosition: 1}
{id: 4, item: 126, lineNum: 0, linePosition: 2}
{id: 5, item: 127, lineNum: 0, linePosition: 3}
{id: 9, item: 130, lineNum: 0, linePosition: 4}
{id: 13, item: 134, lineNum: 0, linePosition: 5}
{id: 3, item: 125, lineNum: 1, linePosition: 7}
{id: 7, item: 128, lineNum: 1, linePosition: 2}
{id: 12, item: 133, lineNum: 1, linePosition: 3}
{id: 10, item: 131, lineNum: 2, linePosition: 1}
{id: 8, item: 129, lineNum: 3, linePosition: 3}
{id: 14, item: 135, lineNum: 3, linePosition: 9}
{id: 15, item: 136, lineNum: 3, linePosition: 2}
{id: 11, item: 132, lineNum: 4, linePosition: 5}
]
Array.prototype.sort()
let arr = getData();
arr.sort(function(a, b) {
if( a.lineNum === b.lineNum ) {
return a.item - b.item;
} else {
return a.lineNum - b.lineNum;
}
});
// return a.lineNum === b.lineNum ? a.item - b.item : a.lineNum - b.lineNum;
for( let i = 0; i < arr.length; i++ ) {
if( arr[i].lineNum > 0 ) break;
arr[i].linePosition = i;
}
// Used classic loop, to break it and avoid unnecessary iterations.
console.log( JSON.stringify(arr).replace(/\},/g, "},\n") );
/***/
function getData() {
return [
{id: 11, item: 132, lineNum: 4, linePosition: 5},
{id: 2, item: 124, lineNum: 0, linePosition: 2},
{id: 9, item: 130, lineNum: 0, linePosition: 5},
{id: 12, item: 133, lineNum: 1, linePosition: 3},
{id: 15, item: 136, lineNum: 3, linePosition: 2},
{id: 13, item: 134, lineNum: 0, linePosition: 4},
{id: 10, item: 131, lineNum: 2, linePosition: 1},
{id: 8, item: 129, lineNum: 3, linePosition: 3},
{id: 1, item: 123, lineNum: 0, linePosition: 5},
{id: 3, item: 125, lineNum: 1, linePosition: 7},
{id: 5, item: 127, lineNum: 0, linePosition: 9},
{id: 7, item: 128, lineNum: 1, linePosition: 2},
{id: 4, item: 126, lineNum: 0, linePosition: 4},
{id: 14, item: 135, lineNum: 3, linePosition: 9},
];
}
.as-console-wrapper { max-height: 100vh !important; }
You can do the mentioned task by using Javascript .sort() function. It can take a optional compare function parameter which specifies a function that defines the sort order.
let arr = [
{id: 11, item: 132, lineNum: 4, linePosition: 5},
{id: 2, item: 124, lineNum: 0, linePosition: 2},
{id: 9, item: 130, lineNum: 0, linePosition: 5},
{id: 12, item: 133, lineNum: 1, linePosition: 3},
{id: 15, item: 136, lineNum: 3, linePosition: 2},
{id: 13, item: 134, lineNum: 0, linePosition: 4},
{id: 10, item: 131, lineNum: 2, linePosition: 1},
{id: 8, item: 129, lineNum: 3, linePosition: 3},
{id: 1, item: 123, lineNum: 0, linePosition: 5},
{id: 3, item: 125, lineNum: 1, linePosition: 7},
{id: 5, item: 127, lineNum: 0, linePosition: 9},
{id: 7, item: 128, lineNum: 1, linePosition: 2},
{id: 4, item: 126, lineNum: 0, linePosition: 4},
{id: 14, item: 135, lineNum: 3, linePosition: 9}
];
//sorting the given array, first based on lineNum, then by item
arr.sort(function(a,b){
if(a.lineNum !== b.lineNum)
return a.lineNum - b.lineNum;
return a.item - b.item;
});
// modify each object where lineNum===0, linePosition starting from 0
// since we have sorted, break when first lineNum > 0
let linePos = 0;
for( let i = 0; i < arr.length; i++ ) {
if( arr[i].lineNum > 0 )
break;
if(arr[i].lineNum === 0)
arr[i].linePosition = linePos++;
}
// console.log(arr); //<-- This prints as array
console.log( JSON.stringify(arr).replace(/\},/g, "},\n") ); // <-- This prints your mentioned format
Hope this helps !
I am trying to save react-seat-picker
https://github.com/roggervalf/react-seat-picker#readme
data into firestore and read it back.
The one piece of code describing data that should be written/saved to firestore is this:
const rows = [
[{id: 1, number: 1, isSelected: true, tooltip: 'Reserved by you'}, {id: 2, number: 2, tooltip: 'Cost: 15$'}, null, {id: 3, number: '3', isReserved: true, orientation: 'east', tooltip: 'Reserved by Rogger'}, {id: 4, number: '4', orientation: 'west'}, null, {id: 5, number: 5}, {id: 6, number: 6}],
[{id: 7, number: 1, isReserved: true, tooltip: 'Reserved by Matthias Nadler'}, {id: 8, number: 2, isReserved: true}, null, {id: 9, number: '3', isReserved: true, orientation: 'east'}, {id: 10, number: '4', orientation: 'west'}, null, {id: 11, number: 5}, {id: 12, number: 6}],
[{id: 13, number: 1}, {id: 14, number: 2}, null, {id: 15, number: 3, isReserved: true, orientation: 'east'}, {id: 16, number: '4', orientation: 'west'}, null, {id: 17, number: 5}, {id: 18, number: 6}],
[{id: 19, number: 1, tooltip: 'Cost: 25$'}, {id: 20, number: 2}, null, {id: 21, number: 3, orientation: 'east'}, {id: 22, number: '4', orientation: 'west'}, null, {id: 23, number: 5}, {id: 24, number: 6}],
[{id: 25, number: 1, isReserved: true}, {id: 26, number: 2, orientation: 'east'}, null, {id: 27, number: '3', isReserved: true}, {id: 28, number: '4', orientation: 'west'}, null,{id: 29, number: 5, tooltip: 'Cost: 11$'}, {id: 30, number: 6, isReserved: true}]
]
You can stringify your nested array (JSON.stringify(rows)) before storing in firestore and parse it after getting it back.
So far firebase firestore doesn't support nested arrays,you need to change the data structure.Have a look at this solution
I have an array from the api response and its objects.I need to find the value which has maximum total and I have display it I'm unable to solve it , when there are two max values of the total.Is there any solution?
myArray[
{time: "2018-12-02", total: 25, percentage: 20, averageTime: 20},
{time: "2018-13-02", total: 25, percentage: 20, averageTime: 20},
{time: "2018-14-02", total: 35, percentage: 25, averageTime: 25},
{time: "2018-16-02", total: 65, percentage: 60, averageTime: 20},
{time: "2018-17-02", total: 40, percentage: 20, averageTime: 20},
{time: "2018-18-02", total: 65, percentage: 20, averageTime: 20},
{time: "2018-18-02", total: 35, percentage: 23, averageTime: 20}
];
I tried reduce function like this:
var data =[];
data.reduce((max, p) => p.total > max ? p.total : max, data[0].total);
You can do something like this:
Idea:
Create a hashMap with total as keys and a variable to hold max value.
Check if the key exists and if not, initialize it to an array.
Push current object in this array.
Fetch the array with the key as max and you will get all the values with max total.
Now that you have entire object, you can iterate and display any necessary values.
var myArray = [{time: "2018-12-02", total: 25, percentage: 20, averageTime: 20},
{time: "2018-13-02", total: 25, percentage: 20, averageTime: 20},
{time: "2018-14-02", total: 35, percentage: 25, averageTime: 25},
{time: "2018-16-02", total: 65, percentage: 60, averageTime: 20},
{time: "2018-17-02", total: 40, percentage: 20, averageTime: 20},
{time: "2018-18-02", total: 65, percentage: 20, averageTime: 20},
{time: "2018-18-02", total: 35, percentage: 23, averageTime: 20}]
var max = 0;
var hashMap = myArray.reduce((acc, p) => {
max = Math.max(max, p.total);
acc[p.total] = acc[p.total] || [];
acc[p.total].push(p);
return acc;
}, {});
console.log(hashMap[max]);
With only time value
var myArray = [{time: "2018-12-02", total: 25, percentage: 20, averageTime: 20},
{time: "2018-13-02", total: 25, percentage: 20, averageTime: 20},
{time: "2018-14-02", total: 35, percentage: 25, averageTime: 25},
{time: "2018-16-02", total: 65, percentage: 60, averageTime: 20},
{time: "2018-17-02", total: 40, percentage: 20, averageTime: 20},
{time: "2018-18-02", total: 65, percentage: 20, averageTime: 20},
{time: "2018-18-02", total: 35, percentage: 23, averageTime: 20}]
var max = 0;
var hashMap = myArray.reduce((acc, p) => {
max = Math.max(max, p.total);
acc[p.total] = acc[p.total] || [];
acc[p.total].push(p.time);
return acc;
}, {});
console.log(hashMap[max]);
You can use Math.max along with spread and array.prototype.map:
var myArray = [
{time: "2018-12-02", total: 25, percentage: 20, averageTime: 20},
{time: "2018-13-02", total: 25, percentage: 20, averageTime: 20},
{time: "2018-14-02", total: 35, percentage: 25, averageTime: 25},
{time: "2018-16-02", total: 65, percentage: 60, averageTime: 20},
{time: "2018-17-02", total: 40, percentage: 20, averageTime: 20},
{time: "2018-18-02", total: 65, percentage: 20, averageTime: 20},
{time: "2018-18-02", total: 35, percentage: 23, averageTime: 20}
];
var max = Math.max(...myArray.map(e => e.total));
console.log(max);
You can find the maximum 'total' value in the array and then find all the elements of the array with that maximum value.
var myArray = [
{time: "2018-12-02", total: 25, percentage: 20, averageTime: 20},
{time: "2018-13-02", total: 25, percentage: 20, averageTime: 20},
{time: "2018-14-02", total: 35, percentage: 25, averageTime: 25},
{time: "2018-16-02", total: 65, percentage: 60, averageTime: 20},
{time: "2018-17-02", total: 40, percentage: 20, averageTime: 20},
{time: "2018-18-02", total: 65, percentage: 20, averageTime: 20},
{time: "2018-18-02", total: 35, percentage: 23, averageTime: 20}
];
var max = Math.max(...myArray.map(e => e.total));
var time = myArray.filter(item => item.total == max);
console.log(time);
One possible approach:
function getMaxValue(myArray) {
var totals = myArray.map(x => x.total);
var max = filter(x => x == Math.max(totals));
return max.length == 1 ? max[0] : 'unable to solve it';
}