-
-
Save caseyjustus/1166258 to your computer and use it in GitHub Desktop.
function median(values) { | |
values.sort( function(a,b) {return a - b;} ); | |
var half = Math.floor(values.length/2); | |
if(values.length % 2) | |
return values[half]; | |
else | |
return (values[half-1] + values[half]) / 2.0; | |
} | |
var list1 = [3, 8, 9, 1, 5, 7, 9, 21]; | |
median(list1); |
@impari Unfortunately in javascript this isn't the case. You can test this using the following:
[10, 5].sort()
@alireza-saberi's fix along with a second function for already sorted arrays. The median should be just as fast to calculate for massive arrays as little ones, provided the input is already sorted.
function median(values) {
values = values.slice(0).sort( function(a, b) {return a - b; } );
return middle(values);
}
function middle(values) {
var len = values.length;
var half = Math.floor(len / 2);
if(len % 2)
return (values[half - 1] + values[half]) / 2.0;
else
return values[half];
}
var list1 = [3, 8, 9, 1, 5, 7, 9, 21];
median(list1);
list1.sort(function(a, b) {return a - b; });
middle(list1);
@willstott101 I believe your if-statement is wrong, when len is even then len % 2
will return 0, and the code will jump to the else
. OP has it the other way around and it is correct. Better yet have len % 2 === 0
so that it is easier to understand at a glance, and not have to think about len % 2
returning 1 or 0 which then evaluates to true or false, etc..
For reference, here's the median()
function of lodash.math:
math.median = function(arr) {
arr = arr.slice(0); // create copy
var middle = (arr.length + 1) / 2,
sorted = math.sort(arr);
return (sorted.length % 2) ? sorted[middle - 1] : (sorted[middle - 1.5] + sorted[middle - 0.5]) / 2;
};
nice !
Similar to lodash.math
but without the custom sort method and a little more readable (in my opinion):
function median(numbers) {
const middle = (numbers.length + 1) / 2;
const sorted = [...numbers].sort((a, b) => a - b); // avoid mutating when sorting
const isEven = sorted.length % 2 === 0;
return isEven ? (sorted[middle - 1.5] + sorted[middle - 0.5]) / 2 : sorted[middle - 1];
}
EDIT: fixed as per @henrikra's comment.
@sqren, Thanks, worked like a charm.
@sqren Otherwise you answer was good but the number sorting didn't work
This version will work!
function median(numbers: number[]) {
const middle = (numbers.length + 1) / 2;
const sorted = [...numbers].sort((a, b) => a - b); // you have to add sorting function for numbers
const isEven = sorted.length % 2 === 0;
return isEven ? (sorted[middle - 1.5] + sorted[middle - 0.5]) / 2 : sorted[middle - 1];
}
@danielbayerlein sort
will mutate the array. I used the spread operator to instead return a new shallow copy. Before the spread operator concat
and slice
did the trick:
arr.concat().sort()
# or
arr.slice(0).sort()
Some more discussion on this topic https://stackoverflow.com/questions/9592740/how-can-you-sort-an-array-without-mutating-the-original-array
@sqren Thank you for the explanation.
@danielbayerlein You are welcome.
Btw. Noticed your project https://github.com/danielbayerlein/git-pick. I've create a tool called backport
: https://github.com/sqren/backport
Looks like we are doing something similar :D
I would also check the length first. if it is zero return. no need to proceed further.
@ MichalPaszkiewicz Hello what is the use of the function(a,b) {return a - b;} it will sort it anyhow even if list1.sort().