I am trying to add multiple arrays in javascript.
Here are my arrays I have made, and are working.
function getAmountSpent(){
var amountSpent = ((Math.random() * 500) + 1);
return amountSpent.toFixed(2)
}
function getGift(){
var gift = ((Math.random()* 50) + 1);
return gift.toFixed(2)
}
var names = ["Jeremy","Arun","Alisa","Rohan","Dana"];
var spent = [];
for (let i = 0; i < 5; i++) {
spent.push(getAmountSpent());
}
var gifts = [];
for (let i = 0; i<5; i++) {
gifts.push(getGift());
}
What I need help with is adding these arrays in a new function. I have began writing the code, and I am not sure what is wrong.
var totals =[];
for (let i=0; i<5; i++) {
totals.push(getSumTotals())
}
function getSumTotals(a){
totals= spent+(spent * gifts);
return totals.toFixed(2)
}
From what you can see, I am trying to add up the totals much like this:
totals[0] = spent[0] + (spent[0] * gifts[0]);
totals[1] = spent[1] + (spent[1] * gifts[1]);
totals[2] = spent[2] + (spent[2] * gifts[2]);
totals[3] = spent[3] + (spent[3] * gifts[3]);
totals[4] = spent[4] + (spent[4] * gifts[4]);
if it helps, the professor added guided instructions for function getSumTotals(a) stating:
This function will return the sum of the elements in array a.
You will be passing the array that holds your totals to
the parameter a. Be sure to treat the values in a as numbers.
I am not sure if this helps but here is the output to my document.
Current Total should equal (spent) + (spent * gifts). For instance, for Jeremy in this example, current total should equal:
$36.55 + ($36.55*0.0626) = $38.83. Since there are many variables involved, I am not 100% sure what I should write for function getSumTotals(a)
The parameter "a" is a placeholder because I am not sure how many parameter values I need, and the proper format I need to use.
As for the code...
You're both
not passing an index to getSumTotals
not using this parameter within getSumTotals to access your spent and gifts arrays
var totals =[];
for (let i=0; i<5; i++) {
totals.push(getSumTotals(i)) // you were missing i
}
function getSumTotals(idx) { // I took liberties to rename this
totals = spent[idx] + (spent[idx] * gifts[idx]);
return totals.toFixed(2);
}
Now for the Math...
All that said, this math of spent[i] + spent[i] * gifts[i] doesn't make much sense either. Was this specified in the problem?
you may use like this
defined gifts
gifts=[45,43,32];
defined spends
spends=[43,32,21];
this is the getSumTotal funtion
getSumTotal=(x)=>(x.a+x.b)
this is where added
totals=gifts.map((d1,i)=>{
return fu({a:gifts[i],b:spends[i]})
})
I understand this is your assignment, however - if the idea is to both generate arrays, and then add them together, it is a redundant step. Just use the name array to iterate once and do all your calculations within that single loop.
Here, I had some fun and took some liberties, but hopefully you see why multiple arrays are redundant.
function getSumTotals() {
const getAmountSpent = () => Math.random() * 500 + 1;
const getGift = () => Math.random() * 50 + 1;
const names = ["Jeremy", "Arun", "Alisa", "Rohan", "Dana"];
let totals = []
names.forEach((name, i) => {
let spent = getAmountSpent()
let gifts = getGift()
let $$$ = (spent + spent * gifts).toFixed(2);
totals[i] = $$$
console.log(`${name} cost me $${$$$}${'!'.repeat(($$$/1000) | 1)}`)
});
return totals;
}
getSumTotals()
Note, that toString returns a type of "String", but not "Number".
When you try to sum a number with string, you get a concatenated string "1" + 2 = "12"
To turn a string into Number, you must use a Number("str") function, or just a bunary + before the string:
console.log( "1" + 2 );
console.log( Number("1") + 2 );
console.log( +"1" + 2 );
Also, you use the same loop 3 times, but can use just one loop instead, and call all functions inside the one loop. And use your array.length instead of fixed number 5:
let names = ["Jeremy", "Arun", "Alisa", "Rohan", "Dana"];
let spent = [];
let gifts = [];
let totals = [];
for (let i = 0; i < names.length; i++) {
spent.push( getAmountSpent() );
gifts.push( getGift() );
totals.push( getSumTotals(i) );
}
console.log( totals );
function getAmountSpent() {
return rand(1, 500, 2);
}
function getGift() {
return rand(1, 50, 2);
}
function getSumTotals(i) {
return +( spent[i] * ( 1 + gifts[i] ) ).toFixed(2);
}
function rand(from, to, fixed = 0){
return +(Math.random()*( to - from ) + from).toFixed(fixed);
}
P.s. Math.random() returns a number between 0 (included) and 1 (not included). If you need a random number between (example) 20 and 100, Math.random()*(100-20) will give a number between 0 and 80. After adding +20 to the result, you get a number from 20 to 100. That's what does this formula Math.random()*( to - from ) + from
P.P.s. Another way, to get the same thing:
var names = ["Jeremy", "Arun", "Alisa", "Rohan", "Dana"].reduce( (prev, elem) => {
let spent = rand(1, 500, 2);
let gift = rand(1, 50, 2);
prev[elem] = new UserData( spent, gift );
return prev;
}, {});
console.log( "Jeremy spent: " + names.Jeremy.spent );
console.log( names );
function rand(from, to, fixed = 0){
return +(Math.random()*( to - from ) + from).toFixed(fixed);
}
function UserData(spent, gift){
this.spent = spent;
this.gift = gift;
this.total = +(spent * ( 1 + gift )).toFixed(2);
}
/* Google → Array reduce, Constructor functions */
function getAmountSpent(){
let amountSpent = ((Math.random() * 500) + 1);
return Number(amountSpent.toFixed(2))
}
function getGift(){
let gift = ((Math.random()* 50) + 1);
return Number(gift.toFixed(2))
}
let names = ["Jeremy","Arun","Alisa","Rohan","Dana"];
let spent = [];
let gifts = [];
let totals =[];
for (let i = 0; i < names.length; i++) {
spent.push(getAmountSpent());
gifts.push(getGift());
totals[i] = (spent[i]+(spent[i] * gifts[i])).toFixed(2);
totals[i] = parseFloat(totals[i])
}
Hi there
I don't think you need a function to add the totals. you just need to loop through and assign totals[i] to spent[i] + (spent[i] * gifts[i]).
then you can use the parseFloat and toFixed function to change the string to a number. remember toFixed() function turns numbers to string. so you need to use the parseFloat to change it to number again as shown in the code above. or you can come up with an easy way of changing it to number. I hope this helps!
Related
I am playing around with JavaScript while preparing for my junior developer interview.
I am trying to write a function that accepts two parameters, a beginning point and an ending point, in an array. This function should generate a random name within a custom start and end point of the array. I seemed close to getting it right, but it displays NaN. What is NaN?
Here is the code I wrote.
const names = ['Kitana', 'Liu Kang', 'Sonya Blade', 'Johnny Cage', 'Jax Briggs', 'Smoke', 'Sheeva', 'Jade']
const section = document.querySelector('section')
const para = document.createElement('p');
// Add your code here
function random(beginIndex, endIndex) {
for (let beginIndex = 0; beginIndex < names.length; beginIndex = beginIndex + endIndex) {
let newRangeOfIndices = names[beginIndex]
const randomName = Math.floor(Math.random() * newRangeOfIndices)
para.textContent = randomName
}
}
random(2, 5)
// Don't edit the code below here!
section.innerHTML = ' ';
section.appendChild(para);
<section></section>
You will notice that I already set a custom limit in the function to be run, 2 to 5. But it's still not working. Please help me out.
You don't for loop to get a random number.
To get a random index.
let randomIndex = Math.floor(Math.random() * (endIndex - beginIndex + 1) + beginIndex)
Then get the random name from the names array.
let randomName = names[randomIndex]
const names = ['Kitana', 'Liu Kang', 'Sonya Blade', 'Johnny Cage', 'Jax Briggs', 'Smoke', 'Sheeva', 'Jade']
const section = document.querySelector('section')
const para = document.createElement('p');
// Add your code here
function random(beginIndex, endIndex) {
let randomIndex = Math.floor(Math.random() * (endIndex - beginIndex + 1) + beginIndex)
let randomName = names[randomIndex]
para.textContent = randomName
}
random(2, 5)
// Don't edit the code below here!
section.innerHTML = ' ';
section.appendChild(para);
<section></section>
The author asked two questions here...
the first one related to the code and here is my solution:
const names = ['Kitana', 'Liu Kang', 'Sonya Blade', 'Johnny Cage', 'Jax Briggs', 'Smoke', 'Sheeva', 'Jade'];
// create a generic randomName function that takes 3 parameters beginIndex, endIndex and an array which returns a random positioned value within the range
function randomName(beginIndex, endIndex, arr) {
const randomNumber = Math.floor(Math.random() * (endIndex - beginIndex + 1) + beginIndex);
return arr[randomNumber];
}
// call the function with the proper argument
randomName(2, 5, names);
the second question is What is NaN?
Answer: as stated by MDN Docs
The global NaN property is a value representing Not-A-Number.
When calculating numbers but sending a string value to parse, the JavaScript parser is throwing an error that it is Not-A-Number.
let's see we have two variables
let x = 10;
let y = 'hello';
console.log(typeof x); // number
console.log(typeof y); // string
// try to multiplied x by y
console.log(x * y); // NaN
In Your case:
function random(beginIndex, endIndex) {
for (let beginIndex = 0; beginIndex < names.length; beginIndex = beginIndex + endIndex) {
// this will be a string that extracts the value of the beginIndex position value from the names array.
let newRangeOfIndices = names[beginIndex]
// here you try to multiply the Random Number by a string and getting NaN
const randomName = Math.floor(Math.random() * newRangeOfIndices)
para.textContent = randomName
}
}
random(2, 5)
Best wishes for your interview
Use:
return Math.random() * (max - min) + min;
To get a number as min-max. Then, use the random number output as an index in the array. Always avoid for loops in situations like this - there is most likely always another way to do it.
Math.floor(Math.random()* (max_number)+min_number)
you are using string not index number.
newRangeOfIndices is giving the value of particular index.
this will work.
I have an array of number
[350000, 350000, 350000]
I have the following code:
function getNPV(rate, periods, Cashflow) {
var npv = 0;
for (var i = 0; i < Cashflow.length; i++) {
npv += Cashflow[i] / Math.pow(1 + rate, periods);
}
return npv;
}
Here, cashflow is our array, rate = 6% and period = 91days.
When I take :
npv = Cashflow[i] / Math.pow(1 + rate, periods);
The output is [348328,346664,344952] when 6% discount rate is applied to 350000 each time.
I am trying to take the sum of [348328,346664,344952] which is $1,039,944
But, it is giving me $1034856 as the result.
Trying the console, it's actually taking the sum of the 3rd value 3 times instead. [344952+344952+344952] for some reason.
Can someone please tell me how to fix this error. Any help is appreciated. Thank you.
As I refer to your spreadsheet, you need an array for period not cashflow.
Pass periods and cashflow like:
var periods = [30, 60, 91];
var cashflow = 350000;
getNPV(rate, periods, cashflow);
Your cash flow is same, so no need an array (You may still have an array if you want to vary cashflow)
And use it in the loop:
function getNPV(rate, periods, Cashflow) {
var npv = rate;
for (var i = 0; i < periods.length; i++) {
npv += Cashflow / Math.pow(1 + rate, periods[i]);
}
return npv;
}
You can use returnSum to get the sum of the array
function returnSum(arr) {
function sum(a, b) {
return a + b;
}
return arr.reduce(sum, 0);
}
let array = [348328,346664,344952]
returnSum(array); //result 1039944
I am trying to randomize colors by generating random number, then applying
it to array to get an color array containing font-color and background-color.
At every "skill" I want to have unique color scheme. So each time I loop skill array I loop color array to fetch color scheme. If this color scheme number (which is same as the randomNumber) is already in use I random again. I do this with do/while loop. When color is not found it pushes it to usedColors array and paints the picture.
For some reason I am still getting same colors. I pasted two pictures to the bottom. Console.log image is about usedColors array (the randomly generated numbers)
var usedColors = [];
$.each(knowledges, (i, knowledge) => {
do {
var r = Math.floor(Math.random() * Math.floor(colors.length)),
rColors = colors[r];
} while ($.inArray(r, usedColors) == 0);
usedColors.push(r);
$("#knowledges div").append(
$("<p />").addClass("knowledge").text(knowledge).css({"background-color": rColors[0], "color": rColors[1]})
);
});
inArray gives position of the matching element. So compare against -1, to know that element is not present in the usedColors array.
var usedColors = [];
$.each(knowledges, (i, knowledge) => {
do {
var r = Math.floor(Math.random() * Math.floor(colors.length)),
rColors = colors[r];
} while ($.inArray(r, usedColors) != -1);
usedColors.push(r);
$("#knowledges div").append(
$("<p />").addClass("knowledge").text(knowledge).css({"background-color": rColors[0], "color": rColors[1]})
);
});
To generate array of unique numbers from certain interval you can do this.
In your case the range will be 0, arr.length - 1.
// function that will generate random unique random numbers between start
// and end, and store already generated numbers in closure
function generateUniqueRandom(start, end) {
const used = [];
function generateInner() {
let r;
while (!r) {
r = Math.floor(Math.random() * (end - start) + 1) + start;
if (used.includes(r)) {
r = null;
} else {
used.push(r);
}
}
return r;
}
return generateInner;
}
const random1 = generateUniqueRandom(0, 20);
const nums1 = [];
for (let i = 0; i < 10; i++) {
nums1.push(random1());
}
console.log(nums1);
const random2 = generateUniqueRandom(0, 20);
const nums2 = [];
for (let i = 0; i < 20; i++) {
nums2.push(random2());
}
console.log(nums2);
But you need to be careful not to generate more numbers that the specified range is, otherwise you will be stuck in an infinite loop.
In your while loop, are you checking if the array is unique? If so, it looks like you may not be using $.inArray correctly.
Put this in your while loop:$.inArray(r, usedColors) !== -1
jQuery.inArray(), how to use it right?
I think your loop method has many interactions, I mean your loop is traveling so much that it only ends until you find the random number that is not in the array (A short performance problem). An alternative method so that the array elements are random:
function shuffleArray(a) {
for (let i = a.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[a[i], a[j]] = [a[j], a[i]];
}
return a;
}
const colors = [["black","green"], ["white","blue"], ["pink","white"]];
let usedColors = shuffleArray(colors);
//You can now do this:
$.each(knowledges, (i, knowledge) => {
$("#knowledges div").append(
$("<p />").addClass("knowledge").text(knowledge).css({"background-color": usedColors[i][0], "color": usedColors[i][1]})
);
});
As you can see from the embed below... my script is only returning one result(500). How can I rewrite my code so that I get both results? Thank you in advance for your advice.
function multiplier() {
var number = 25;
var multiplier20 = 20;
if (number && multiplier20); {
return number * multiplier20;
}
var multiplier1 = 1;
if (number && multiplier1); {
return number * multiplier1;
}
}
multiplier();
EDIT: hey guys thanks for the help. but I figured out what the problem was... I am not supposed to be returning an object only an number. So how do I edit this code to make it return only two numbers???
A function can only return one thing. A generator function (function*) however can yield as many numbers as you want:
function* multiplier() {
yield 25 * 20;
yield 25 * 1;
}
console.log(...multiplier())
You could also turn the results into an array easily:
const array = [...multiplier()];
(No this is not the easiest way, but im trying to propagate some cool js :))
You can try the following approach
function multiplier() {
var number = 25;
var multiplier20 = 20;
var res1 = 0;
var res2 = 0;
if (number && multiplier20); {
res1 = number * multiplier20;
}
var multiplier1 = 1;
if (number && multiplier1); {
res2 = number * multiplier1;
}
return {res1,res2};
}
var ret = multiplier();
console.log(ret);
Or alternatively....
function multiplier() {
return { result1: 25 * 20, result2: 25 * 1 }
}
You can return a string instead of 2 separate number and then, split it into two number. Something like this:
function multiplier(number) {
return number * 20 + '|' + number * 1;
}
var output = multiplier(20)
console.log(output.split('|')[0], output.split('|')[1]);
Okay, so let's say I store some of my data like this,
var thisList = {
"items":[
{"name":"Item1", "image":"/img/item1", "chance":0.25},
{"name":"Item2", "image":"/img/item2", "chance":0.25},
{"name":"Item3", "image":"/img/item3", "chance":0.50}
]
}
Now I'd like to create a function that randomly picks a item out of this list with the chances being 25% of getting [0], another 25% of getting [1] and a 50% chance of getting [2]!
Is this possible? If so, how'd I do this?
Kind regards!
You can actually play it like this, tou generate a number between 0 and 100 and then you cycle on each element and sum the chance to check if it is between the value or not:
var thisList = {
"items":[
{"name":"Item1", "image":"/img/item1", "chance":0.25},
{"name":"Item2", "image":"/img/item2", "chance":0.25},
{"name":"Item3", "image":"/img/item3", "chance":0.50}
]
};
function getRandom(){
var rnd = Math.floor(Math.random() * 100);
console.log("The number is: " + rnd);
var counter = 0;
for(i=0;i<thisList.items.length;i++)
{
counter += thisList.items[i].chance * 100;
if(counter > rnd){
console.log(thisList.items[i]);
break;
}
}
}
getRandom();
EDIT:
If you want to control even with a variant chance you can do this:
var thisList = {
"items":[
{"name":"Item1", "image":"/img/item1", "chance":0.25},
{"name":"Item2", "image":"/img/item2", "chance":0.25},
{"name":"Item3", "image":"/img/item3", "chance":0.50}
]
};
function getRandom(){
var sum = 0;
for(i=0;i<thisList.items.length;i++)
{
sum += thisList.items[i].chance;
}
var rnd = Math.floor(Math.random() * (sum * 100));
console.log("The number is: " + rnd);
var counter = 0;
for(i=0;i<thisList.items.length;i++)
{
counter += thisList.items[i].chance * 100;
if(counter > rnd){
console.log(thisList.items[i]);
break;
}
}
}
getRandom();
You need to look at the cumulative sum of all odds seen so far in the array. With the sample data you've given those values would be 0.25, 0.5, 1.0
Then given a random number in the range [0, 1), just pick the first entry where the cumulative value is less than that number.
Here's an example implementation:
const pickRandom = (() => {
let target = Math.random(), total = 0.0;
return (e, i, a) => {
total += e.chance;
return target < total;
}
});
let picked = thisList.items.find(pickRandom());
The pickRandom function needs to be called exactly once per round, and returns a function that encapsulates the state necessary to accumulate the chances seen so far, and the random number that is to be used.
That function then becomes the predicate used by Array.prototype.find to extract the appropriate random item.