Subtracting all the values inside an array from the first item - javascript

So i have this array of objects that looks like this:
let budgetData = [{title: "Monthly Income", amount: "2500"}, {title:
"rent", amount: "1000"},{title: "car", amount: "200"};
I am trying to some math like this:
2500 - 1000 - 200 = whatever this comes out too. You can continue to add amounts to this array until you have added your monthly expenses.
When you run this the first time with only two values the amount is what you would expect (ie. 2 - 1 = 1).
However add anymore than two amounts to the array it only subtracts whatever the last value is from the first value.(ie. 5 - 2 - 1 = 4).
let amount = [];
for (let i = 1; i < budgetData.length; i++){ amount =
budgetData[0].amount - budgetData[i].amount;
Console.log(amount) === 2300
So this code with the above info the answer comes out to: 2300 when I am expecting it to say 1300.
Where am I going wrong with this, also, is there some built in math function that will do what I am trying to do?

Each time through the loop you're throwing away what you calculated before, and overwriting amount with a new calculation. So what you end up at the very end is just subtracting the very last number from the first number.
Instead, you need to keep a running tally. Something like this:
let budgetData = [
{title: "Monthly Income", amount: "2500"},
{title: "rent", amount: "1000"},
{title: "car", amount: "200"}
];
let amount = budgetData[0].amount;
for (let i = 1; i < budgetData.length; i++){
amount = amount - budgetData[i].amount;
}
console.log(amount);

Alternatively you could reduce the array:
const total = budgetData.reduce((previous, current) => (previous.amount || previous) - current.amount);
If your budget objects implement a valueOf method, like this:
class Budget {
constructor(settings){
Object.assign(this, settings);
}
valueOf(){ return this.amount;}
}
budgetData = budgetData.map(el => new Budget(el));
It gets even more beautiful:
const total = budgetData.reduce((a,b) => a-b);

Related

How can I generate a random combination of array elements so that the sum of their values is between two numbers?

Here's a more detailed explanation on what I've tried to achieve and what I want to achieve.
This is for my JavaScript game project for opening a shipment of goods.
Depending on the shipment quality, you can get:
A different random set of items and
a random amount of each item but
the combined value of all items has to be between two minimum and maximum values AND
I want to add some sort of limitation for the amount of each item where I don't want 85 lemons generated because the value of each lemon is 1
I currently have the following:
Let's say that one of my "shipments" is defined as an object.
let shipment = {
name: 'common',
items: ['lemons', 'oranges', 'apples', 'plums'],
minValue: 170,
maxValue: 230
}
Now, out of this object I want to generate the random amount of items so that their sum of values falls between those two min and max values.
The value of each item is stored in my database but for the sake of this example, let's say that their values are defined in a completely different array:
let values = [5, 6, 2, 10]
The order of the elements in the values array corresponds with the value for each item in the items array.
I also want when the algorithm generates an amount for an item in the items array, its pushed into a new result array:
result.push({name: itemName, amount: itemAmount});
So that after the entire generating of those items is done, each item and its corresponding amount generated is an element(object) in the result array that I can use.
I'm using Node.js.
You can generate a random number in that range, then generate 4 weight values to divide that number into 4 unequal parts, here is an example:
let shipment = {
name: 'common',
items: ['lemons', 'oranges', 'apples', 'plums'],
minValue: 170,
maxValue: 230
};
function randomNumberInRange(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
const totalQuantity = randomNumberInRange(shipment.minValue, shipment.maxValue);
const weight1 = randomNumberInRange(1, 97); // 97 is used to make sure the remaining 3 weight can be at least 1
const weight2 = randomNumberInRange(1, 98 - weight1);
const weight3 = randomNumberInRange(1, 99 - (weight1 + weight2));
const quantities = [weight1, weight2, weight3]
.map((v) => (v / 100))
.map((v) => Math.floor(totalQuantity * v));
quantities.push(totalQuantity - quantities.reduce((a, c) => (a + c))); // set the 4th weight to be equal to the remaining quantity
shipment.items = shipment.items.map((name, index) => ({ name, quantity: quantities[index] }))
console.log(shipment);
The 4 generated values are not that random, the first one will tend to be bigger than the rest, the second one will tend to be smaller than the first but bigger than the third and forth and so on.

How to I change the value of a property of an object on a function click in javascript?

employees = [{Id: 1001, Salary : 2000}, {Id: 1002, Salary: 1000}];
Expected Results:- I am displaying the above array on the browser. On a function click, I want the Salary to get multiplied by 12. ie the annual salary should be displayed on the web page. However on the function click I am multiplying the salary by using the map() of array and then pushing the newly calculated annual salary into the Salary property
Actual Results:- The newly calculated salary property is not getting pushed into the property of the students array.
code snippet:-
map() {
this.annualSalary = this.students.map(a => a.Salary * 12 );
this.annualSalary.forEach((as, index) => {
let asalary = as;
this.students.push({
Salary : asalary,
});
});
Here is your solutions
for (let index = 0; index < this.students.length; index++) {
const element = this.students[index];
this.students[index].Salary = element.Salary * 12
}

ecommerce; Howto create weighfactors to use in calculation (based on the category of products)?

When a client completes an order, steps are as follows:
We will get the weighfactors based on the category for each product. (in a lookup table)
Per product, the calculation will be made using the price, quantity and weigh factor
The sum of all the products individual calculation will be the new conversionvalue passed on to Google Ads using the conversionpixel.
Instead of the revenue reported by our website we want to work with a different number that better represent the actual sales that go through. We want to work with new "actual" values in order to be able to use automated bidding strategies in Google Ads: For instance: phones have a 25% acceptance rate, so if 4 phones of €500 are sold, 3 of them will probably be cancelled. If the conversion value would be €125 each time- this way 4 sales will make €500 revenue together and be a good estimate of actual revenue instead of theoretical revenue.
4*500 - 3*500 = 500 = 4*125
We want to implement a new google pixel on the clients website where we want to communicate the new conversion value to Google Ads. But in order to make this happen we need several things:
-Full overview of the shoppingbaskets transaction products when someone checks out on the website. This mostly contains SKU, Name, Price, Quantity
-A table that depicts the weighfactor of every category
-A piece of javascript that reads out the shopping basket and calculates the new total conversionvalue based on pricequantityweighfactor for each product
-A Google Ads conversion pixel in which we parse the new conversionvalue
In the site we have a piece of code when there's a conversion:
This array below is called transactionProducts:
transactionProducts: [
{ Sku: 'dd44', Name: 'tshirt', Category: 'apparel1', Price: 1.99, Quantity: 2, },
{ Sku: 'AA1243544', Name: 'socks', Category: 'apparel2', Price: 9.99, Quantity: 3, }
]
There's a lookup table where apparel1 converts to 0.5 and apparel2 converts to 0.2 values; So in the end my final conversionvalue should look like this;
2*1.99*0.5 + 3*9.99*0.2 = 1.99 + 5.994 = 7.984
I wanted to create a piece of javascript that makes the sum of the products for every product in the array. Below is what i got so far, but since i'm not a javascript pro i need some assistance with this.
function() {
var sum = 0 for (var i = 0; i < {{VAR - transactionProducts}}.length; i++){
sum += {{VAR - transactionProducts}}[i]['quantity']*{{VAR - transactionProducts}}[i]['price']*{{VAR - Datalayer - Pricefactor Category LookupTable}}
};
return sum;
}
I get response 16.975. so there IS a mistake womewhere. After calculating i noticed i used 0.5 as a factor for all calculations as shown below;
2*1.99*0.5 + 3*9.99*0.5 = 1.99 + 14.985 = 16.975
Not sure what went wrong here since my javascript knowledge isnt that extensive. My best guess is that it has to do with the variable that goes in the Lookup table. The output factor remains constant ('apparel1'-->0.5) but it has to fluctuate based on which calculation we're trying to make.
The inputfunction in the lookuptable goes like this;
function() {
for (var i = 0; i < {{VAR - transactionProducts}}.length; i++){
var cat = {{VAR - transactionProducts}}[i]['category']
return cat
};
}
That's the situation.
function() {
var lookupTable = {
'Apparel1': function() {
return 0.5;
},
'Apparel2': function() {
return 0.4;
},
'Apparel3': function() {
return 0.25;
},
'Apparel4': function() {
return 2;
}};
var sum = 0
for (var i = 0; i < {{VAR - transactionProducts}}.length; i++){
sum += {{VAR - transactionProducts}}[i]['quantity']*{{VAR - transactionProducts}}[i]['price']*
lookupTable[{{VAR - transactionProducts}}[i]['category']]()
};
return sum;
}

Pulling values from an array based on date?

I have an array of data points, [date, value], like so...
data_points = [[1310279340, 1], [1310279340, 1]]
I need to create an array based on "milliseconds ago", with ten values for each second, or a value for every 100ms going backwards.
The new array's values will look like, [ms ago, value], like so...
ms_ago_points = [[0,3],[100,6],[200,7]]
So the last value in that array represents [200ms ago, value of 7].
I'm having a hard time figuring out how to get "value from Xms ago" based on date values in the first array. If needed I might be able to get the initial date/values in a format other then an array if it would be easier to poll for data.
Thanks for any guidance!!
edit: I'm looking to repeat the same value between dates for every 100ms tick that lands between them.
var now = Date.now(),
l = data_points.length,
ms_ago_points = [];
for ( var c = 0; c < l; c++ ) {
ms_ago_points.push([now - data_points[c][0],data_points[c][1]);
}
Maybe you need to sort the ms_ago_points afterwards, but this should give you your desired array.
However: I'd seriously suggest you not to work with multi-dimesional arrays but objects instead:
ms_ago_points= [{ms: 0, value: 3},{ms:100, value: 6}...]
*edit: This of course assumes that your data_points are already in 100ms steps, otherwise you'd have to implement an interpolation :)
I believe this meets your requirements:
function msFromDataPoints(nowTime, dataPoints) {
var d = dataPoints.length,
i = 0,
anchor = Math.floor(nowTime.getTime() / 100) * 100,
ms = anchor,
msArr = [];
while (d--) {
while (ms >= data_points[d][0] * 1000) {
msArr.push([anchor - ms, dataPoints[d][1]];
ms -= 100;
}
}
return msArr;
}
See it in a Js Fiddle.
Note: I find the data structures to be a little strange. An object for the input seems best:
[{date: 1310279340, value: 1}, {date: 1310279340, value: 1}]
And your output array doesn't need the milliseconds at all, as simply [1, 1, 5, 5, 3, 2 4] (or whatever) would be understood to mean millisecond indexes starting at 0 and increasing by 100. If absolutely required, you could use a sparse array:
result = [];
result[0] = 1;
result[100] = 1;
result[200] = 5; // and so on

How to randomly return associative array names based on its values

I've a set of campaigns that correspond to a number of "points." Looks something like this:
[ {"c1":4, "c2":8, "c3":25} ]
I want to randomly pick a campaign from this set. I'm assuming rand() will come into play at some point. However, I want the value of each to affect its chances of being picked.
So, for example, campaign "c2" should be picked twice as often as campaign "c1" (roughly). "c3" would be king, being most likely to be picked.
The number of campaigns and corresponding values may or may not be the same every time the script runs.
What's a good way to go about this?
That's easy.
Just create another map that have CDF value for each campaign. For your example it will be:
0.108: C1
0.324: C2
1: C3
Then get a random number between 0 and 1. Go through the map and find the smallest number that is larger than the random number (you can binary search it or create a sorted hash map that can give smallest larger number also)
Note that by adding the probabilities the last entry may not add to 1 (can be 0.999). Just set it to 1 manually.
Here's a function that solves this for you. It creates a weighting array that you can use with a random number to properly weight each item per it's weighted value.
var campaigns = {"c1":4, "c2":8, "c3":24};
function getWeightedRandomCampaign(list) {
var weighting = [];
var total = 0;
for (var item in list) {
weighting.push({key: item, value: list[item]});
total += list[item];
}
// generate random number between 1 and total
var rand = Math.floor(Math.random() * total);
// figure out which weighted slot it fits in
var cum = 0;
for (var i = 0; i < weighting.length; i++) {
cum += weighting[i].value;
if (rand < cum) {
return(weighting[i].key);
}
}
return(weighting[weighting.length - 1]);
}
You can see it work here: http://jsfiddle.net/jfriend00/ffwqQ/
Here's how it works.
It starts with the campaigns objects and the weighting values.
var campaigns = {"c1":4, "c2":8, "c3":24};
Then, it builds a temporary data structure that looks like this:
var weighting = [{key: "c1", value: 4}, {key: "c2", value: 8}, {key: "c3", value: 24}];
While creating that data structure, it keeps track of the running total of all weight values.
It then creates a random number between 0 and that total.
It then walks through the weighting array adding up the values to find the first cumulative value that exceeds the random number. When it finds that, this is the slot that was selected.

Categories