subtract Object value into array is not correct - javascript

l am trying to sum total price from array object then add the total price outside that array.
example :
[
{
"addons": [
{
"title": "خبز بعجين",
"price": 0.1,
"selected": true
},
{
"title": "لحم بعجين ",
"price": 2,
"selected": true
},
{
"title": "ببسي بارد",
"price": 55,
"selected": true
},
{
"title": "كولا ",
"price": 4,
"selected": true
}
],
"Totaladdons": 61.1, // < total price of array above .
"price" : 300 // < sum Totaladdons with this object price .
}
]
sum(data) {
let totalPrice = 0;
let currency: any
currency = this.items_local[data.index].addons.map(curr => parseFloat(curr.price)).reduce((a, b) => a + b, 0)
console.log(currency);
this.items_local[data.index].Totaladdons = Number(currency);
if (this.items_local[data.index].Totaladdons) {
totalPrice = Number(this.items_local[data.index].Totaladdons) + Number(this.items_local[data.index].price)
this.items_local[data.index].price = totalPrice.toFixed(2)
}
}
Minus method to remove element array object then resuming total price
minus(data) {
if (this.items_local[data.index].addons.length > 0) {
for (var i = this.items_local[data.index].addons.length - 1; i >= 0; i--) {
if (this.items_local[data.index].addons[i].title === data.addon.title) {
this.items_local[data.index].addons.splice([i], 1);
// here l am try to resuming the price of array object
currency = this.items_local[data.index].addons.map(curr => parseFloat(curr.price)).reduce((a, b,) => a - b, 0);
console.log(currency);
if (this.items_local[data.index].Totaladdons) {
this.items_local[data.index].Totaladdons = Number(currency);
totalPrice = Number(this.items_local[data.index].price) - Number(this.items_local[data.index].Totaladdons)
this.items_local[data.index].price = totalPrice.toFixed(2)
}
}
}
}
}
The problem is when l click on the minus method he is not giving me the correct total number.

Related

How group students with different scores in leveled groups

I need to create groups of students to work together, but i need to level the groups using his grades. So, i don't want only the good grades students in one hand and the bad grades on other. I want to mix them all using his grades to randomize that.
So, i have the name and the score for every student. I need 3 homework groups, so i calculated the score of all / 3. To know the value who every single group need.
Now it's the problem, i don't know how can i insert the students in this groups without be over the max value for one group and how guarantee every group with same number of students.
Until now, i make this:
var totalScore = 0;
for (var i = 0; i < students.length; i++) {
totalScore = totalScore + students[i].score;
}
var maxScoreForGroup = totalScore / 3;
console.log(maxScoreForGroup);
for (var o = 0 ; o < students.length; o++) {
if ((students[o].score + homeWork1[0].scoreTotal) < maxScoreForGroup) {
homeWork1[0].students.push(students[o].name);
homeWork1[0].scoreTotal = homeWork1[0].scoreTotal + students[o].score;
} else if ((students[o].score + homeWork2[0].scoreTotal) < maxScoreForGroup) {
homeWork2[0].students.push(students[o].name);
homeWork2[0].scoreTotal = homeWork2[0].scoreTotal + students[o].score;
} else {
homeWork3[0].students.push(students[o].name);
homeWork3[0].scoreTotal = homeWork3[0].scoreTotal + students[o].score;
}
}
But i'm getting in homeWork1 only 2 students with score 10 each, in homework2 only 2 students with score 10 and 7.5, and in homework 3 every other student.
How can i change this to get 3 groups with 3 students and every group with the same score total?
My array of students
var students = [
{
"name": "Charles",
"score": 10
},
{
"name": "Max",
"score": 10
},
{
"name": "Samuel",
"score": 10
},
{
"name": "Carl",
"score": 7.5
},
{
"name": "James",
"score": 7.5
},
{
"name": "Frank",
"score": 7.5
},
{
"name": "George",
"score": 5
},
{
"name": "Timothy",
"score": 5
},
{
"name": "Paul",
"score": 5
},
]
My output is
"[{"scoreTotal":20,"students":["Charles","Max"]}]"
"[{"scoreTotal":17.5,"students":["Samuel","Carl"]}]"
"[{"scoreTotal":30,"students":["James","Frank","George","Timothy","Paul"]}]"
I made this fiddle too
Here's another approach that might work for you.
We shuffle the students array, split into groups of n students (in this case 3), then get the total scores of each group.
If the groups have the same total score we add to our possibleGroups array.
You can change the number of attempts or just repeat to get different groupings.
const students = [ { "name": "Charles", "score": 10 }, { "name": "Max", "score": 10 }, { "name": "Samuel", "score": 10 }, { "name": "Carl", "score": 7.5 }, { "name": "James", "score": 7.5 }, { "name": "Frank", "score": 7.5 }, { "name": "George", "score": 5 }, { "name": "Timothy", "score": 5 }, { "name": "Paul", "score": 5 }, ]
function shuffle(arr) {
for (let i = arr.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[arr[i], arr[j]] = [arr[j], arr[i]];
}
return arr;
}
function getTotalScore(a) {
return a.reduce((total, student) => total + student.score, 0);
}
function allEqual(a) {
return (new Set(a).size) === 1;
}
function split(a, groupSize) {
return a.reduce((sums, x, idx) => {
if (idx % groupSize === 0) {
sums.push([]);
}
sums[sums.length - 1].push(x);
return sums;
}, [])
}
let attempts = 20;
let n = 3;
let possibleGroups = [];
for(let i = 0; i < attempts; i++) {
let groups = split(shuffle([...students]), n);
let scores = groups.map(getTotalScore);
if (allEqual(scores)) {
possibleGroups.push( { scoreTotal: scores[0], groups } );
}
}
console.log('Possible groupings:');
possibleGroups.forEach((group, idx) => {
console.log(`Grouping ${idx + 1}:`);
console.log(JSON.stringify(group, null, 2))
})
.as-console-wrapper { max-height: 100% !important; }

Javascript manipulating json issue

[
{
"timing": [
{
"zone": 18.8
},
{
"zone": 17.06,
},
{
"zone": 16.6
},
]
},
{
"timing": [
{
"zone": 12.6,
},
{
"zone": 14.6,
}
]
},
{
"timing": [
{
"zone":19.06,
},{
"zone": 8.06,
}
]
}
]
Here i am trying to work manipulate with one json data using javascript.
But, I am not able to think any approach how to achive that.
I am expecting below json. It give zone1, zone2, zone3 as per the zone any it will be dynamically
Please have a look to below json.
[
{
"zone1": [18.8, 12.6, 19.06 ]
},{
"zone2": [17.06, 14.6, 8.06]
}, {
"zone3":[16.6]
}
]
This is the output of json how it should look like.
Please have a look
You can use reduce and forEach
Loop through data, set OP's initial value as an object
Loop through timing property of each element, check if the zone + index + 1 exists in op or not, if exists push zone to that key else initialise new key
let data = [{"timing": [{"zone": 18.8},{"zone": 17.06,},{"zone": 16.6},]},{"timing": [{"zone": 12.6,},{"zone": 14.6,}]},{"timing": [{"zone": 19.06,}, {"zone": 8.06,}]}]
let final = data.reduce((op, { timing }) => {
timing.forEach(({ zone }, i) => {
let key = `zone${ 1 + i }`
op[key] = op[key] || []
op[key].push(zone)
})
return op
}, {})
console.log(final)
// If you need final output to be array of object just use entries and map to build a desired output
console.log(Object.entries(final).map(([k,v])=>({[k]:v})))
Here's a possible solution
var data = [{
"timing": [{
"zone": 18.8
},
{
"zone": 17.06,
},
{
"zone": 16.6
},
]
},
{
"timing": [{
"zone": 12.6,
},
{
"zone": 14.6,
}
]
},
{
"timing": [{
"zone": 19.06,
}, {
"zone": 8.06,
}]
}
];
// Calculate the total number of zones
var totalZones = 0;
for (let i = 0; i < data.length; i++) {
const currZones = data[i].timing.length;
if (currZones > totalZones) totalZones = currZones;
}
console.log(totalZones);
// Create the final Array
var result = new Array(totalZones);
for (let i = 0; i < totalZones; i++) {
result[i] = {
zone: []
}
}
// Populate the final array with values
for (let i = 0; i < totalZones; i++) {
for (let j = 0; j < data.length; j++) {
let currTiming = data[j].timing[i];
if (currTiming !== undefined) {
let currZone = data[j].timing[i].zone;
if (currZone !== undefined) {
result[i].zone.push(currZone);
}
}
}
}
console.log(result);
1) Gather all zone values into one array of array
2) Calculate max rows needed for zones
3) Have a simple for-loop till max rows and use shift and push methods.
const data = [
{
timing: [
{
zone: 18.8
},
{
zone: 17.06
},
{
zone: 16.6
}
]
},
{
timing: [
{
zone: 12.6
},
{
zone: 14.6
}
]
},
{
timing: [
{
zone: 19.06
},
{
zone: 8.06
}
]
}
];
const zones = data.map(time => time.timing.map(z => z.zone));
const rows = zones.reduce((rows, arr) => Math.max(rows, arr.length), 0);
const all = [];
for (let index = 1; index <= rows; index++) {
const res = [];
zones.forEach(zone => zone.length > 0 && res.push(zone.shift()));
all.push({ [`zone${index}`]: res });
}
console.log(all);
const input = [ {"timing": [{"zone": 18.8},{"zone": 17.06,},{"zone": 16.6},]},{"timing": [{"zone": 12.6,},{"zone": 14.6,}]},{"timing": [{"zone":19.06,},{"zone": 8.06,}]}]
var data = input.map(t => t.timing.map(u => u.zone));
var output = data[0].map((col, i) => data.map(row => row[i])).map((item, index) => {res = {}; res["zone"+(index+1)] = item.filter(t => t!==undefined); return res});
console.log(output);
Not the shortest, but it's very readable.
var json = [{"timing": [{"zone": 18.8},{"zone": 17.06,},{"zone": 16.6},]},{"timing": [{"zone": 12.6,},{"zone": 14.6,}]},{"timing": [{"zone": 19.06,}, {"zone": 8.06,}]}];
// index 0 is zone1, index 1 is zone2, index 2 is zone3, and so on ...
var zones = [];
// Loop through each 'timing' object
json.forEach(function(timingObject) {
var timing = timingObject['timing'];
// loop through each 'zone' in the given 'timing' object
timing.forEach(function(zoneObject, index) {
var zone = zoneObject['zone'];
// if the zone exists in the zones[] defined above
// add the current zone to its place
//
// if not (else), we have to add the array for the
// current index, then add the value of the current zone.
if(zones[index]) {
zones[index]['zone' + (index + 1)].push(zone);
} else {
zones.push({ ['zone' + (index + 1)]: [zone]})
}
});
});
console.log(zones);

For loop with Javascript to get values

I have this variable named: var quantity.
This variable changes continuously. For example: quantity = 1, quantity = 26...
On the other hand I have an array of elements with prices according to the quantity of the product: var quantity_prices.
var quantity_prices = [
{
"quantity": 1,
"price_pvp": 7.96
}, {
"quantity": 5,
"price_pvp": 7.96
}, {
"quantity": 15,
"price_pvp": 6.97
}, {
"quantity": 25,
"price_pvp": 5.97
}
];
I want to make that if quantity is between quantities 1 and 5, 6 and 14, 15 and 24, the product has the right price.
Example:
if the quantity is 16, the price I want to take is: 5,95€.
I've thought about using a for loop but I don't know how to continue to make this work what I want to do:
for (var i = 0; i < this.quantity_prices.length; i++) { // if quantity is between 1 and 5
new_price = this.quantity_prices[i].price_pvp;
// elseif quantity is between 6 and 14
new_price = this.quantity_prices[i].price_pvp;
// elseif quantity is between 15 and 24
new_price = this.quantity_prices[i].price_pvp;
}
var quantity_prices = [
{
"quantity": 1,
"price_pvp": 7.96,
},
{
"quantity": 5,
"price_pvp": 7.96,
},
{
"quantity": 15,
"price_pvp": 6.97,
},
{
"quantity": 25,
"price_pvp": 5.97,
}
];
for(let i=0;i<quantity_prices.length;i++){
if(quantity_prices[i].quantity>0 && quantity_prices[i].quantity<5 )
{
//whatever the required output you want.
quantity_prices[i].new_price=quantity_prices[i].price_pvp;
}if(quantity_prices[i].quantity>6 && quantity_prices[i].quantity<14){
}
if(quantity_prices[i].quantity>15 && quantity_prices[i].quantity<24){
}
}
console.log(quantity_prices)
Here try it with this:
function check(){
this.quantity_prices.find(({price}) => {
if(price_pvp > 1 && price_pvp < 5){
// do something
}
if(price_pvp > 6 && price_pvp < 14){
// do something
}
if(price_pvp > 15 && price_pvp < 24){
// do something
}
}
}
You can group according to your req as per below code and then print the price.
var quantity_prices = [{
"quantity": 1,
"price_pvp": 7.96,
},
{
"quantity": 5,
"price_pvp": 7.96,
},
{
"quantity": 15,
"price_pvp": 6.97,
},
{
"quantity": 25,
"price_pvp": 5.97,
}
];
var group1_5 = quantity_prices.filter(q => q.quantity >= 1 && q.quantity <= 5);
console.log(group1_5);
//print your price
if (group1_5.length > 0) {
console.log(group1_5[0].price_pvp)
}
var group6_16 = quantity_prices.filter(q => q.quantity >= 6 && q.quantity <= 14);
console.log(group6_16);
You can search for the right quantity, then return the price for this amount.
I'm assuming that if the quantity is not found directly we'll return the next entry in the quantity / price table.
const quantity_prices = [ { "quantity": 1, "price_pvp": 7.96, }, { "quantity": 5, "price_pvp": 7.96, }, { "quantity": 15, "price_pvp": 6.97, }, { "quantity": 25, "price_pvp": 5.97, } ];
function getPrice(quantity, priceLookup) {
let entry = priceLookup.find((e,index) => e.quantity >= quantity || index === priceLookup.length-1);
return entry.price_pvp;
}
console.log("Price table:");
const quantities = [1,4,5,10,15,16,25,26,30];
for(let quantity of quantities ) {
console.log(`Price (${quantity }): €${getPrice(quantity, quantity_prices)}`);
}

How to optimize array grouping?

I have an array that is constantly updated and accordingly it is necessary to update its grouping. Example of an array:
[
{
"price": 2419.62,
"amount": 0.0266
},
{
"price": 1927.52,
"amount": 0.0217
},
...
]
I tried different options. At the moment this option is the fastest:
const points = [
{
"price": 2419.62,
"amount": 0.0266
},
{
"price": 1927.52,
"amount": 0.0217
},
...
];
const range = 500;
const spread = 1800;
const countGroup = 250;
const sizeUnitGroup = range / countGroup;
const groups = {};
for (let i = 0; i < countGroup; i++){
groups[i] = [];
try {
points.forEach((item, id) => {
if (item.price > spread + (i*sizeUnitGroup) && item.price <= spread + (i*sizeUnitGroup + sizeUnitGroup)){
groups[i].push(item);
points.splice(id, 1);
}
if (item.price > (spread + (i*sizeUnitGroup + sizeUnitGroup))) throw BreakException;
});
} catch (e) {
}
}
But even so, this function works for too long. Any ideas how this can be optimized?
You could calculate the interval for pushing the value to the wanted slot.
var points = [
{ price: 2419.62, amount: 0.0266 },
{ price: 1927.52, amount: 0.0217 },
{ price: 1800, amount: 0.07 }, // -1 not in result
{ price: 1800.000000000001, amount: 0.07 }, // 0
{ price: 1802, amount: 0.07 }, // 0
],
range = 500,
spread = 1800,
countGroup = 250,
sizeUnitGroup = range / countGroup,
groups = {};
points.forEach((item, id) => {
var i = Math.ceil((item.price - spread- sizeUnitGroup) / sizeUnitGroup);
if (i >= 0 && i < countGroup) {
groups[i] = groups[i] || [];
groups[i].push(item);
}
});
console.log(groups);
.as-console-wrapper { max-height: 100% !important; top: 0; }

How to get quanity rate from the given json data in angularjs

Json Data :
{
"food": {
"rates": {
"defaultRates": {
"cardRate": 600,
"discountedRate": 500
},
"otherRates": [
{
"cardRate": 600,
"discountedRate": 400,
"fields": [
{
"name": "Quantity",
"min": 3,
"max": 6
}
],
"name": "3-6 Quantity"
},
{
"cardRate": 600,
"discountedRate": 300,
"fields": [
{
"name": "Quantity",
"min": 7
}
],
"name": "7+ Quantity"
}
]
},
"details" : {
"name" : "Something"
}
}
JS Code:
$scope.food = angular.copy(JSONObject); // Copied JsonObject
$scope.defaultRates = angular.copy($scope.food.rates.defaultRates);
$scope.otherRates = angular.copy($scope.food.rates.otherRates);
$scope.quantity = 4;
angular.forEach($scope.otherRates, function (otherRate) {
angular.forEach(otherRate.fields, function (field) {
if($scope.quantity >= field.min){
if(field.max) {
if($scope.quantity <= field.max){
$scope.discountedRate = angular.copy(otherRate.discountedRate);
}
} else {
$scope.discountedRate = angular.copy(otherRate.discountedRate);
}
} else {
$scope.discountedRate = angular.copy($scope.defaultRates.discountedRate);
}
})
});
If I console the $scope.discountedRate I'm getting the 7+ quantity rate. I want to get the $scope.discountedRate according to the $scope.quantity I have given.
So, How to get the discounted rate from the json data by comparing the quantity of the food.
You need to iterate over otherRates as follows.
var qty = what ever the user selects
var matched = {};
angular.forEach(food.otherRates, function(otherRate){
angular.forEach(otherRate.fields, function(field){
if(field.min <= qty && field.max >= qty)
matched = otherRate;
else if(field.min <= qty)
matched = otherRate;
});
});
console.log(matched);
//matched is the other Rate

Categories