How can i find median values from array in javascript
this is my array
var data = [
{ values: 4 },
{ values: 4 },
{ values: 4 }
For an array of numbers, e.g. [1,6,3,9,28,...]
// calculate the median
function median(arr){
arr.sort(function(a, b){ return a - b; });
var i = arr.length / 2;
return i % 1 == 0 ? (arr[i - 1] + arr[i]) / 2 : arr[Math.floor(i)];
}
What the code is doing:
In your question, your array can be flattened like so:
var myArray = data.map(function(d){ return d.values; });
And to get the median, use the function above like so:
var myMedian = median(myArray); // 4.5
Here's a snippet that allows you to generate an array of numbers with either even or odd length. The snippet then sorts the array and calculates the median, finally printing the sorted array and the median.
(function() {
function makeNumArray(isEven) {
var randomNumArr = [];
var limit = isEven ? 8 : 9;
for (var i = 0; i < limit; i++) {
randomNumArr.push(Math.ceil(Math.random() * 10));
}
return randomNumArr;
}
function getMedian(arrOfNums) {
var result = [];
var sortedArr = arrOfNums.sort(function(num1, num2) {
return num1 - num2;
});
result.push("sortedArr is: [" + sortedArr.toString() + "]");
var medianIndex = Math.floor(sortedArr.length / 2);
if (arrOfNums.length % 2 === 0) {
result.push((sortedArr[medianIndex-1] + sortedArr[medianIndex]) / 2);
return result;
} else {
result.push(sortedArr[medianIndex]);
return result;
}
}
function printMedian(resultArr) {
var presentDiv = document.querySelector('#presentResult');
var stringInsert = '<div id="sortedArrDiv">' + resultArr[0].toString() + '<br>' + 'the median is: ' + resultArr[1].toString() + '</div>';
if (!document.querySelector('#sortedArrDiv')) {
presentDiv.insertAdjacentHTML('afterbegin', stringInsert);
} else {
document.querySelector('#sortedArrDiv').innerHTML = resultArr[0].toString() + "<br>" + 'the median is: ' + resultArr[1].toString();
}
};
function printEven() {
printMedian(getMedian(makeNumArray(1)));
}
function printOdd() {
printMedian(getMedian(makeNumArray(0)));
}
(document.querySelector("#doEven")).addEventListener('click', printEven, false);
(document.querySelector("#doOdd")).addEventListener('click', printOdd, false);
})();
#presentResult {
width: 70%;
margin: 2% 0;
padding: 2%;
border: solid black;
}
<h4>Calculate the median of an array of numbers with even (static length of 8) or odd (static length of 9) length. </h4>
<input type="button" value="Even length array of random nums" id="doEven">
<input type="button" value="Odd length array of random nums" id="doOdd">
<div id="presentResult"></div>
Findmedian(arr) {
arr = arr.sort(function(a, b){ return a - b; });
var i = arr.length / 2;
var result = i % 1 == 0 ? parseInt((arr[i - 1] + arr[i]) / 2) + ',' +
parseInt(arr[i]) : arr[Math.floor(i)];
return result;
}
it returns for odd number of array elements.
This will do what you need - at the moment you've no logic to cope with reading the .values
field out of each element of the array:
function findMedian(data) {
// extract the .values field and sort the resulting array
var m = data.map(function(v) {
return v.values;
}).sort(function(a, b) {
return a - b;
});
var middle = Math.floor((m.length - 1) / 2); // NB: operator precedence
if (m.length % 2) {
return m[middle];
} else {
return (m[middle] + m[middle + 1]) / 2.0;
}
}
EDIT I've padded out the code a bit compared to my original answer for readability, and included the (surprising to me) convention that the median of an even-length set be the average of the two elements either side of the middle.
In case you were wondering how to find median without using conditionals, here you are :)
Mind ES6.
/**
* Calculate median of array of numbers
* @param {Array<Number>} arr
* @return {Number}
*/
function median(arr) {
arr = [...arr].sort((a, b) => a - b);
return (arr[arr.length - 1 >> 1] + arr[arr.length >> 1]) / 2;
}
To answer the question:
median(data.map(x => x.values));
Here about two things you have to be careful.
1) Operator precedence
When you are saying
var middle = m.length - 1 / 2;
It is same as
var middle = m.length - 0.5; //Because / has much precedence than -
So you should say
var middle = (m.length - 1) / 2;
Same problem with m.length - 1 % 2
2) You are not rounding middle
so it's looking for decimal indexes in array. Which I think will return undefined
.