I am writing a function called "computeAverageOfNumbers".
Given an array of numbers, "computeAverageOfNumbers" returns their average.
Notes:
If given an empty array, it should return 0.
Here's my code:
function computeAverageOfNumbers(nums) {
var total = 0;
for (var i = 0; i < nums.length; i++) {
total += nums[i];
}
var avg = total / nums.length;
return avg;
}
var input = [];
var output = computeAverageOfNumbers(input);
console.log(output); // --> returns NaN instead of 0
As you can see my code returns NaN when you submit an empty array but works if you put regular array items like var input = [1,2,3,4,5];
If given an empty array, it should return 0.
Am I missing something?
Just do below
if( nums.length == 0 ) return 0;
in code
function computeAverageOfNumbers(nums) {
if (nums.length == 0) return 0;
var total = 0;
for (var i = 0; i < nums.length; i++){
total += nums[i];
}
var avg = total / nums.length;
return avg;
}
Just check if nums.length
function computeAverageOfNumbers(nums) {
if (nums.length === 0) {
return 0
} else {
var total = 0;
for (var i = 0; i < nums.length; i++) {
total += nums[i];
}
var avg = total / nums.length;
return avg;
}
}
var input = [];
var output = computeAverageOfNumbers(input);
console.log(output);
input = [2,5,9,13];
output = computeAverageOfNumbers(input);
console.log(output);
When your array is empty, nums.length = 0 and a if you divide a number by 0, it gives you NaN.
Just change
var avg = total / nums.length;
to
var avg = (nums.length)?total/nums.length:0
to solve your trouble
When you pass an empty array then this line:
var avg = total / nums.length;
Is a division by zero, so avg will be NaN. I would short circuit the function at the start with:
if (nums.length === 0)
return 0;
Bear in mind ideally you also want to do some type checking to confirm you've got an array, etc. but the above should give you the basics.
when I run this program I end up with NaN at the end; I'd appreciate some form of explanation, as I'm stumped! I have an odd feeling it has to do something with scope...
https://jsfiddle.net/Smuggles/evj46a23/
var array = []
var range = function(start, end) {
for (var count = start; count <= end; count++) {
array.push(start);
start += 1;
}
console.log(array);
}
var sum = function() {
var result = 0
var arrayLength = array.length
for (var count = 0; count <= arrayLength; count++) {
result += array[count]
console.log(result);
}
}
console.log(sum(range(1, 10)));
2 things:
You need to change the for loop in the sum function to be < arrayLength and not <= arrayLength. You are dealing with array lengths which start with a 0 index.
You need to return the result from the sum function
var array = [];
var range = function(start, end) {
for (var count = start; count <= end; count++) {
array.push(start);
start += 1;
}
};
var sum = function() {
var result = 0;
var arrayLength = array.length;
for (var count = 0; count < arrayLength; count++) {
result += array[count];
}
return result;
};
console.log(sum(range(1, 10)));
Given an array of [4,5,6], the indexes would be as follows:
0: 4
1: 5
2: 6
Therefore, when you use the length property of the array (3), you are referencing an index that does not exist, which returns undefined. It tries to do the math on the undefined, which causes a NaN. This is why you have to use < arrayLength.
The functional approach:
It would help to make those functions a bit more "pure". Instead of maintaining state outside of the functions (with var array = []), just return the values from the functions: See the following for example:
function range(start, end) {
var arr = [];
for (var i = start; i <= end; i++) {
arr.push(i);
}
return arr;
}
function sumArray(array) {
return array.reduce(function(a, b) {
return a + b;
});
}
console.log(sumArray(range(1, 10)));
Each function takes arguments, and simply returns the result. This way, you approach this a little more "functional".
Description in Comments of Code
var array = [];
var range = function(start, end) {
//simplified the loop to remove unnecessary variables
for (; start <= end; start++) {
array.push(start);
}
return array;
}
var sum = function() {
var result = 0;
// move length to scope of the loop
// change to < rather than <= due to zero index nature of arrays
for (var count = 0, length = array.length; count < length; count++) {
result += array[count];
}
// return the result from the function
return result;
}
// gets an array from 1-10
var arr = range(1, 10);
// print the array to the console
console.log(arr);
// print the sum to the console
console.log(sum(arr));
Starting with this initial 2D array:
var initialArray = [[2,3],[6,7],[4,5],[1,2],[5,6],[2,3]];
I need to create this 3D array programmatically:
var fullArray = [
[[2,3],[6,7],[4,5],[1,2],[5,6],[2,3]],
[[3,4],[0,1],[5,6],[2,3],[6,7],[3,4]],
[[4,5],[1,2],[6,7],[3,4],[0,1],[4,5]],
[[5,6],[2,3],[0,1],[4,5],[1,2],[5,6]],
[[6,7],[3,4],[1,2],[5,6],[2,3],[6,7]],
[[0,1],[4,5],[2,3],[6,7],[3,4],[0,1]],
[[1,2],[5,6],[3,4],[0,1],[4,5],[1,2]],
[[2,3],[6,7],[4,5],[1,2],[5,6],[2,3]],
[[3,4],[0,1],[5,6],[2,3],[6,7],[3,4]],
[[4,5],[1,2],[6,7],[3,4],[0,1],[4,5]],
[[5,6],[2,3],[0,1],[4,5],[1,2],[5,6]]
];
See the pattern?
On each pair, the [0] position should increment to 6 (from any starting number <= 6) and then reset to 0 and then continue incrementing. Similarly, the [1] position should increment to 7 (from any starting number <= 7) and then reset to 1 and then continue incrementing.
In this example, there are 10 2D arrays contained in the fullArray. However, I need this number to be a variable. Something like this:
var numberOf2DArraysInFullArray = 12;
Furthermore, the initial array should be flexible so that initialArray values can be rearranged like this (but with the same iteration follow-through rules stated above):
var initialArray = [[6,7],[2,3],[5,6],[4,5],[1,2],[6,7]];
Any thoughts on how to programmatically create this structure?
Stumped on how to gracefully pull this off.
Feedback greatly appreciated!
Here's a solution, I've separated the methods, and I made it so if instead of pairs it's an N size array and you want the [2] to increase up to 8 and reset to 2, if that's not needed you can simplify the of the loop for(var j = 0; j < innerArray.length; j++)
var initialArray = [[2,3],[6,7],[4,5],[1,2],[5,6],[2,3]];
var create3DArray = function(array, size){
var newArray = [initialArray];
for(var i = 0; i < size; i++)
{
newArray.push(getNextArrayRow(newArray[i]));
}
return newArray;
}
var getNextArrayRow = function(array){
var nextRow = [];
for(var i = 0; i < array.length; i++)
{
var innerArray = array[i];
var nextElement = [];
for(var j = 0; j < innerArray.length; j++)
{
var value = (innerArray[j] + 1) % (7 + j);
value = value === 0 ? j : value;
nextElement.push(value);
}
nextRow.push(nextElement);
}
return nextRow;
}
console.log(create3DArray(initialArray,3));
Note, the results from running the snippet are a bit difficult to read...
var initialArray = [[2,3],[6,7],[4,5],[1,2],[5,6],[2,3]];
var numOfArrays = 10;
// get a range array [0, 1, 2, ...]
var range = [];
for (var i = 0; i < numOfArrays; i++) {
range.push(i);
}
var result = range.reduce(function(prev, index) {
if (index == 0) {
return prev;
}
prev.push(transformArray(prev[index - 1]));
return prev;
}, [initialArray])
console.log(result);
function transformArray(arr) {
return arr.map(transformSubArray)
}
function transformSubArray(arr) {
return arr.map(function(val) {
return val == 7 ? 0 : val + 1;
})
}
Here's a pretty simple functional-ish implementation
Given :
var array = [1,2,5,10];
var limit = 8;
I am looking for a way to find the biggest element of the array, less than the limit 8. something like :
Math.max(array, "while < limit");
I tried :
Math.min(Math.max(array), limit)
which does not work in all cases for array and limit, obviously.
EDIT :
The input array is not necessarily sorted :
var array = [10,-10,10,-10];
var limit = 5;
Expected result is -10.
var array = [1,2,5,10];
var limit = 8;
alert(Math.max.apply(Math, array.filter(function(x){return x <= limit})));
You can sort, filter and then pop
var array = [1,2,5,10];
var limit = 8;
var largest = array.sort().filter(item => (item < limit)).pop();
console.log(largest);
You can either just do a simple for loop, you can filter all numbers less than the max and sort and max, or you can use reduce which is just like doing a for loop.
for loop (could use forEach)
var array = [1, 2, 5, 10];
var limit = 8;
var result = array[1];
for (var i = 1; i < array.length; i++) {
if (array[i] <= limit && array[i] > result) {
result = array[i];
}
}
console.log(result);
Filter with Max
var array = [1, 2, 5, 10];
var limit = 8;
var result = Math.max.apply([], array.filter(function(val) {
return val < limit
}));
console.log(result);
Reduce
var array = [1,2,5,10];
var limit = 8;
var temp = array[0];
var result = array.reduce( function (num, val ) {
return val > num && val <= limit ? val : num
}, temp);
console.log(result)
You can try in this way:
var array = [1,2,5,10,7];
var limit = 8;
var max=0;
for(var i=0;i<array.length;i++)
{
if(array[i] > max && array[i] < limit)
max=array[i];
}
console.log(max);
var array = [1,2,5,10];
var limit = 8;
var closest = null;
array.forEach(function(el){
if (el <= limit && (closest == null || (limit - el) < (limit - closest))) {
closest = el;
}
});
alert(closest);
My goal is to make a randomly generated 2D Array in Javascript, that has an X amount of the same one character value while the rest of the values are equal to another character.
In this example, there are 10 rows and 10 columns for the 2D Array. 20 out of the possible 100 values of the Array should be equal to 'Y' (for yes) and the 80 others should be 'N' (for no). I want the 'Y's to be randomly placed all over the Array, and I absolute need exactly 20 of them to be 'Y's and the rest 'N's.
I had a less efficient way before, and I thought to try this approach, where after I define the Array, I make the first X amount of values a 'Y' and then the rest all 'N's. Then I shuffle the array, (using the shuffle from the underscore library) so that the 'Y's are all spread out randomly everywhere.
Is this an efficient way of getting what I need done? Are there any better solutions? I tried making a JSFiddle with my example, but the site appears to be down at the moment.
(I was unable to test my code yet to see if the shuffle worked correctly on my 2D array)
var rows = 10;
var cols = 10;
var elements = 20;
//Define Empty Array
var test = new Array(rows);
for (var k = 0; k < rows; k++)
{
test[k] = Array(cols);
}
var i = 1;
for (var x = 0; x < rows; x++)
{
for (var y = 0; y < cols; y++)
{
if (i <= elements)
{
test[x][y] = "Y";
}
else
{
test[x][y] = "N";
}
}
}
//Shuffle all those values so they're no longer in order
var shuffledTest = _.shuffle(test);
//Print in rows
for (var x = 0; x < rows; x++)
{
console.log(shuffledTest[x]);
}
A very simple solution is to first create an array, fill it with a number of "N"s, insert the "Y"s at random indexes, and then finally splitting it into the 2-dimensional array that you want:
var tmpArr = [], // Temporary 1-dimensional array to hold all values
arr = [], // The final 2-dimensional array
rows = 10,
cols = 10,
elements = 20; // Number of "Y"s
// 1. Fill temporary array with "N"s
for (var i = 0; i < rows * cols - elements; i += 1) {
tmpArr.push("N");
}
// 2. Insert "Y"s at random indexes in the temporary array
for (var i = 0; i < elements; i += 1) {
var index = Math.round(Math.random() * (tmpArr.length + 1));
tmpArr.splice(index, 0, "Y");
}
// 3. Split temporary array into 10 seperate arrays
// and insert them into the final array
for (var i = 0; i < rows; i += 1) {
var row = tmpArr.slice(i * cols, (i + 1) * cols);
arr.push(row);
}
JSBin to illustrate: http://jsbin.com/luyacora/1/edit
You can try this solution, it uses underscores range to create a pair of arrays to use as iterators, though their values don't matter.
Play around with the randomizer function to get an even distribution of 'y's
JSBIN: http://jsbin.com/yaletape/1/
var rows = _.range(0, 10, 0);
var columns = _.range(0, 10, 0);
function randomizer(mult){
return Math.floor((Math.random()*mult)+1);
}
var y_count = 0;
var matrix = _.map(rows, function(){
return _.map(columns, function(v, i){
var value;
var y_allowed = randomizer(3);
var current_y_count = 0;
if(y_count < 20 && current_y_count < y_allowed){
var rand = randomizer(5);
if(rand > 4){
value = 'y';
current_y_count++;
y_count++;
}
}
if(!value){
value = 'n';
}
return value;
});
});
//The above could be simplified to
var matrix = _.range(0,10,0).map(function(){
return _.range(0,10,0).map(function(){
//put the logic code from above here
});
});
Maybe shuflle a 2D array is not the best way. As #Zeb mentioned, here is some code that fill random positions with the 'Y' value. After that, the other positions are filled with 'N'.
http://plnkr.co/edit/avyKfgsgOSdAkRa1WOsk
var arr = [];
var cols = 10;
var rows = 10;
var positions = rows*cols; // 100
var YQty = 10; // only 10 'Y' are needed
// 'Y' values.
for(i = 0; i < YQty; i++)
{
do
{
x = parseInt(Math.random() * cols);
y = parseInt(Math.random() * rows);
filled = false;
if (typeof(arr[x]) == "undefined")
{
arr[x] = [];
}
if (typeof(arr[x][y]) == "undefined")
{
arr[x][y] = 'Y';
filled = true;
}
}
while (!filled);
}
// 'N' values.
for (x = 0; x < cols; x++)
{
if (typeof(arr[x]) == "undefined")
{
arr[x] = [];
}
for (y = 0; y < rows; y++)
{
if (arr[x][y] != 'Y')
{
arr[x][y] = 'N';
}
}
}
Shuffling the multidimensional array is not the best approach. Seeing as any sort is worse than linear time complexity. The easiest solution would be to create your multidimensional array and then set each index value to the char you want the 'rest' of the values to be. Then for 1 -> the number of other char value choose a random index and set that to the char.
Note: If the randomly picked spot has already been changed you need to choose a new one to make sure you have the right amount at the end.