JavaScript: Find object with Highest & Lowest - javascript

This seemed pretty straight forward,so I was surprised when it did not work. I am trying to find the object with the highest and lowest 'price'. First, please confirm or correct my logic. If, the logic is correct, then please suggest what might be the problem.
var high;
var low;
var j=0;
for (i in obj) {
//alert(obj[i].price);
if(j===0){
high=obj[i].price; low=obj[i].price
}else{
if(obj[i].price > high){high=obj[i].price}
if(obj[i].price < low ){low =obj[i].price}
}
alert("high: " + high +", low: " +low);
j++;
}
Note: This works fine: for (i in obj) { There is another portion of the script that cycles through the list perfectly and with this methodology.

Math.max and Math.min are built-in methods that can be used to find the highest or lowest numbers from the arguments passed. One technique that you can use with these functions is applying them to an array of numbers.
What you have should perform just fine, but if you're looking for something more concise, here's an example of the technique:
var arr = [],
high, low;
for (var i in obj)
arr.push(obj[i].price);
high = Math.max.apply(Math, arr);
low = Math.min.apply(Math, arr);
Example: http://jsfiddle.net/cCexG/
You may also want to add a hasOwnProperty() check to prevent from iterating over enumerable inherited properties. This could possibly be the cause of your current problem, either that or the missing var keyword for the i variable.
for (var i in obj) {
if (obj.hasOwnProperty(i) && obj[i].price)
arr.push(obj[i].price);
}

You can simply sort the array of objects by price in this way:
objects.sort(function(a, b) {
return a.price < b.price ? -1 : 1
});
the code above will sort objects by brice ascending (replace "<" with ">" for descending order)... then you can access the lowest with: objects[0] and the highest with: objects[objects.length-1]

Edit: is working now. I was just going to point out the Math.min() and max but someone beat me to it ;)!
var prices = ["110.5", "110", "350", "255.13", "350.5", "256"];
document.writeln(prices.sort(sortASC));
document.writeln(prices.sort(sortDESC));
function sortASC(a,b){
return parseFloat(a) - parseFloat(b);
}
function sortDESC(a,b){
return parseFloat(b) - parseFloat(a);
}
http://jsfiddle.net/9BSeF/

Related

Get first element in array with index not starting from 0

I'm using a javascript library which returns arrays not starting from zero like starting from 26 or 1500, what i want to do is a method to get the first element in that array regardless of the index number starting with 0 or any other number.
Are they any method to do this in javascript ?
I suggest to use Array#some. You get the first nonsparse element and the index. The iteration stops immediately if you return true in the callback:
var a = [, , 22, 33],
value,
index;
a.some(function (v, i) {
value = v;
index = i;
return true;
});
console.log(index, value);
The information below is generally useful, but for the problem the OP listed, Nina's answer is by far a better solution.
Those are called sparse arrays and they're one of the few situations where you may want to use for-in on an array.
Remember that arrays are objects in JavaScript, and array entries are properties keyed by names (array indexes) that meet certain criteria. So we can use the features that let us discover the properties on an object to find the indexes on your sparse array.
for-in example:
for (var n in theArray) {
if (theArray.hasOwnProperty(n) && isArrayIndex(n)) {
// Use theArray[n]
}
}
This answer shows how you can determine that n is an array index as opposed to being some other property. A very technical definition would be
function isArrayIndex(n) {
return /^0$|^[1-9]\d*$/.test(n) &&
n <= 4294967294;
}
...but a definition that's good enough for most of us would be
function isArrayIndex(n) {
return !isNaN(parseInt(n, 10));
}
Similarly, you can use Object.keys; since it only looks at own enumerable properties, you don't need the hasOwnProperty check:
Object.keys(theArray).forEach(function(n) {
if (isArrayIndex(n)) {
// ...
}
});
Note that officially, neither of those is in any particular order, not even in ES2015 ("ES6"). So in theory, you could see the indexes out of numeric order. In the real world, I've never seen an even vaguely-modern JavaScript engine that returned array indexes out of order. They're not required to, but every one I've tried does.
So officially, you would need to get a full list and then find the minimum value in it:
var min = Object.keys(theArray).reduce(function(min, n) {
var i = parseInt(n, 10);
return isNaN(i) || (min !== undefined && min > i) ? min : i;
}, undefined);
That'll given you undefined if the array is empty, or the min index if it isn't. But if you want to make the assumption you'll get the keys in numeric order:
// Makes an assumption that may not be true
var min = +Object.keys(theArray).filter(isArrayIndex)[0];
If you're using a JavaScript engine that's entirely up-to-date, you can rely on the order returned by Object.getOwnPropertyNames, which is required to list the array indexes in order.
var min = +Object.getOwnPropertyNames(theArray).filter(isArrayIndex)[0];
It may be useful to use a filter function on the array to get back a normalised array.
var fullArray = array.filter(function(n){
return n != undefined;
});
fullArray[0]
The answers here may help you decide Remove empty elements from an array in Javascript
I guess one alternative to Array.prototype.some() is the Array.prototype.findIndex() method. These are much faster than filter alone and will keep your array and indices untouched.
var arr = new Array(1000),
fi = -1;
arr[777] = 1453; // now we have a nice sparse array
fi = arr.findIndex(f => f !== void 0); // void 0 is the perfect undefined
console.log(fi);
console.log(arr[fi]);
With this piece of code you can find first assigned value index and then get the value from your array:
var a = [, , 22, 33];
var value = a.find((v, i) => i in a);
console.log(value);
/* ---------------------------------------------- */
var i = 0
while (!(i in a) && i < a.length) i++; // If i === a.length then the array is emtpy
console.info(i, a[i]);
First implementation uses Array.prototype.find which makes less variable usage so this is cleaner but to find the index you should call indexOf over the array.
But the second one is a little bit old fashioned but give the chance of having index without extra efforts.
BTW Nina's seems better. (can make it shorter?)
const arr = [0,1,2]
// using destructuring to get the first element
let [first] = arr
// plus: using destructuring to get the last element
let [first] = [...arr].reverse()

Javascript for-loop returning "null" instead of my value

I'm trying to get the function below to return the average of all elements in array1, but I keep getting null as the result. I can't seem to figure out why.
var array1 = [46,73,-18,0,-442,779,5,1400];
var arrayAverage = function(arrayavg) {
for (var average = 0,answer=0, arrayavg = arrayavg.length;array1 > answer;answer++)
average +=parseInt(arrayavg[answer]);
var calc = average/arrayavg.length;
return calc
};
There are a number of errors, I don't have time to point them all out, hopefully the following is sufficient:
var array1 = [46,73,-18,0,-442,779,5,1400];
var arrayAverage = function(arrayavg) {
I don't know why you using a function expression rather than a function declaration. It doesn't affect the issue, but is more code to write. It's also good to give variables names that express what they are for, so given that the function expects an array:
function arrayAverage(array) {
then:
for (var average = 0,answer=0, arrayavg = arrayavg.length;array1 > answer;answer++)
It's not a good idea to pile all those variable declarations into the for condition, far better to separate concerns and only create variables that you need:
var total = 0;
Now iterate over the array to get the total value. The '{' brackets can be omitted, but it's clearer to include them:
for (var i=0, iLen=array.length; i<iLen; i++) {
total += array[i];
}
Now calculate the average and return it in one statement:
return total/iLen;
}
console.log(arrayAverage(array1)); // 230.375
You need to put brackets after your for loop
I was too fast to answer.
You are re-assigning the passed array to the length of the passed array.
arrayavg = arrayavg.length
this breaks everything.
in the for loop you have assigned arrayavg=arrayavg.length and in the body ,you are accessing average+=arrayavg[answer]. arrayavg is now a primitive type . it will return undefined.
And your loop condition is array1 > answer array1 is an array .you cant compare it like that.it will return false.
modified code.
var array1 = [46,73,-18,0,-442,779,5,1400];
var arrayAverage = function(arrayavg) {
var sum=0;
for (var i=0;i<arrayavg.length;i++)
sum +=parseInt(arrayavg[i]);
return sum/arrayavg.length;
};
You are comparing a number to your array in your for loop. You want to stop the for when answer is the same as array1 length.
Also, don't change your parameter array to its length if you want to get its values in the loop.
var array1 = [46,73,-18,0,-442,779,5,1400];
var arrayAverage = function(arrayavg) {
for (var average = 0,answer=0, len = arrayavg.length;len > answer;answer++)
average +=parseInt(arrayavg[answer]);
var calc = average/len;
return calc
};
And to call it:
arrayAverage(array1);
Your code has two problems in the for loop.
for (var average = 0,answer=0, arrayavg = arrayavg.length;array1 > answer;answer++)
^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^
First thing is you set arrayavg to arrayavg's length BUT in the next line you try to read the index of the array. Well you overwrote the array with a number! Not going to happen.
Second issue you are comparing an array 'array1' to a number 'answer' . What does that check do? Not what you think it is going. You want to be checking the length, but wouldn't you want to be checking the passed in array, not the hardcoded one?
I think the other answers (particularly RobG) have covered most of it. It might help to follow a couple of standard rules (that I use) for your loops:
1) Always have the index as the first declared element, the length of the array (for caching purposes) as the second, and any other variables after them.
2) Always use brackets to separate your loop code from the code in the rest of the function. That way you know when to return your averaged product (ie after the }).
So this is my slightly rewritten code of your problem:
for (var index = 0, len = arrayavg.length, avg = 0; index < len; index++) {
avg += parseInt(arrayavg[index], 10) / len;
}
return avg;
Note also that parseInt should contain a radix (in this case 10). You can leave it out but it's good practice to always include it.
By the way, here's an alternative to your function you might find useful that uses a functional approach using reduce:
var arrayAverage = function (arr) {
return arr.reduce(function (a, b) { return a + b; }) / arr.length;
}

Eloquent Javascript: The sum of an array

I want a sum function that takes an array of numbers and returns the sum of these numbers.
I wrote the following, but it always returns undefined:
function sum(array){
var sumVar;
for(i = 0; i <= array[array.length]; i++){
sumVar += array[i];
}
return sumVar;
}
console.log(sum([1,2,3]));
// → undefined
Could anyone help explain why this is happening? I'm not so much concerned with the solution as I am with what I'm doing wrong.
While there are multiple areas of your code which seems incorrect (as addressed by #meagar), the reason why you still get undefined after changing your loop iteration to stop at array.length is because you didn't initialize sumVar to 0.
function sum (array) {
var sumVar = 0;
for(var i = 0; i < array.length; i += 1) {
sumVar += array[i];
}
return sumVar;
}
sum( [1, 2] ); // results in 3
Your condition, i <= array[array.length], makes no sense.
You're looping while i is less than array[array.length], which is one-past the last element of the array. This will typically be undefined. i <= undefined is always false, and obviously isn't what you want.
If you want to iterate over each element of the array, i is the index and you need to loop from 0 to one less than array.length. Your condition should be i < array.length.
As #zzzzBov hinted in a comment, there is a more eloquent solution than the imperative loop, a solution involving some functional techniques:
var add = function(a, b) {return a + b;};
var sum = function(nums) {return nums.reduce(add, 0);};
In a library like Ramda, where functions like reduce are curried and the list parameter comes last, this would be even easier (although redundant, since Ramda already includes sum):
var sum = R.reduce(add, 0);
You can try this:
function sumOfArray(array) {
return eval(array.join('+'));
}
console.log(sumOfArray([4,4])); // result 4+4 = 8

What's the fastest way to find the n smallest numbers in an array?

I have a list of numbers and I need to find the n smallest of them.
This is what I have so far, but I'm sure it must be possible to do it faster and cleaner (maybe without having to sort the entire list first?):
var list = [56,34,27,4,78,12,89,1002,45,33,87,90];
var results = [];
var sorted_list = list.slice(); // fastest way to duplicate array
sorted_list.sort(function (a, b) {
return a - b;
});
for (var i = 0; i < n; i++) {
// do stuff with sorted_list[i] and list
// push the result to results
}
return results;
I think if you use a Min Heap to solve this problem, it will be faster. By that I mean
Form a min heap from an array.
Take out the min element and heapify.(This step you will repeat, depending upon how many items you want)
Sorting algorithm will take O(N*logN) time, while Min Heap creation(step 1) will take O(N) time and O(logN){average} will be time taken by the second step.
Note that: Heap is useful when the number of items you needs is less than N. If you repeat the step 2 N times, the total time comes out to O(N*logN) itself same as sorting.
Array.min = function( array ){
return Math.min.apply( Math, array );
};
Source: http://ejohn.org/blog/fast-javascript-maxmin/
Thanks for the clarification. For n elements use:
Array.min = function( array, n ){
return array.sort(function(a, b){return a-b}).slice(0, n);
};
Without sorting it can be done in this way.
Basically the idea is that everytime in each iteration we will push the smallest number in an array.
and will remove that number from the main array
Suppose we have an array of length 12
a=[-11,2,1,5,0,9,-8,6,-10,0,12,4];
and we have to find 4 smallest number
we can find using this function(am is the result array)
function findmin(a) {
var item=Math.min.apply(Math, a);
var index= a.indexOf(item);
am.push(item);
a.splice(index, 1);
if(am.length<n)
findmin(a)
}
Now suppose we have to find 9 smallest number from the array
we can find(12-9=3) max number and remove it from the given array and then that will be our
result.
function findmax(a) {
var item=Math.max.apply(Math, a);
var index= a.indexOf(item);
am.push(item);
a.splice(index, 1);
if(a.length>n)
findmax(a)
}
Here I think the complexity is nm where m is no. of element to be found and n is total no. of element.If I am not wrong.
Actually i am weak in finding complexity.So please suggest if any improvement can be done.
SEE DEMO HERE

Why is the sorting of this object array failing?

I'm trying to sort this object by the score value so I can populate a highscores table. Found this method of sorting which works lovely for sorting smallest to highest with a - in the formula, but when I try and reverse it with a + it doesn't work. I'm confused..
JS:
scores = [
{"n":"Arne", "score":700},
{"n":"Bertil", "score":430},
{"n":"Carl", "score":901},
{"n":"David", "score":30},
{"n":"Eric", "score":23},
{"n":"Frida", "score":118},
{"n":"Greg", "score":221},
{"n":"Hulk", "score":543}
];
scores.sort(function(a, b) {
return a.score + b.score;
});
//add rows to table from scores object
var t = document.getElementById('table');
for (var j in scores) {
var r = document.createElement('tr')
r.innerHTML = '<td><span></span></td><td>'+scores[j].n+'</td><td>'+scores[j].s+'</td>'
t.appendChild(r);
}
You mention that you're trying to reverse the sort, which originally involved subtraction.
Thus I think it's fair to assume that your original sort was like this...
scores.sort(function(a, b) {
return a.score - b.score;
});
If you want to sort in the opposite direction, simply reverse the order of the subtraction:
scores.sort(function(a, b) {
return b.score - a.score;
});
your sort function should return positive , 0 , or negative values
you probably trying to add some numbers there which is a mistake.
try here :
http://jsbin.com/icojaz/edit#javascript,html
it sorts by score.
According to http://www.w3schools.com/jsref/jsref_sort.asp you can see that you just reverse the input parameters like this: return a.score - b.score;

Categories

Resources