Object Setter demo (mean, median, mode and range)
See http://stackoverflow.com/a/26187126/1683264 for an explanation.
by Steve Church
HTML
Data: <span id="data"></span><br>
Mean: <span id="mean"></span><br>
Median: <span id="median"></span><br>
Mode: <span id="mode"></span><br>
Range: <span id="range"></span>
CSS
span { color: purple; font-weight: bold; font-family: Courier}
JavaScript
function $(id) { return document.getElementById(id); }
function out(what,where) { $(where).innerHTML = what; }
var avg = {
// Declaring these items is not necessary. It just helps you
// remember what public values are set by the "dataset" setter
data: [],
mean: null,
median: null,
mode: [],
range: null,
// Object setter
set dataset(arr) {
var isArray = function(obj) {return (Object.prototype.toString.call(obj) === '[object Array]')};
var isNumber = function(n) {return !isNaN(parseFloat(n)) && isFinite(n)};
// sanity checking
if (!isArray(arr)) throw '"' + arr + '" is not an array.';
for (var i=0; i<arr.length; i++) {
if (!isNumber(arr[i])) throw '"' + arr[i] + '" is not a number.';
arr[i]*=1; // if numeric string, convert to number
}
// data (array)
this.data = arr.sort(function(a,b){return a-b});
// mean (float)
this.mean=0;
for (var i=0; i<arr.length; i++) {
this.mean += arr[i];
}
this.mean /= arr.length;
// median (float)
this.median = arr[Math.ceil(arr.length / 2) - 1];
// if even number of values, average the 2 middle numbers
if (!(arr.length % 2)) {
this.median = (this.median + arr[arr.length / 2]) / 2;
}
// mode (array)
var leader = {num:[],freq:0}, contender = {num:null,freq:0};
for (var i=0; i<arr.length; i++) {
if (contender.num === arr[i]) contender.freq++;
else {
contender.num = arr[i];
contender.freq = 1;
}
if (contender.freq == leader.freq) {
leader.num.push(contender.num);
}
else if (contender.freq > leader.freq) {
leader.freq = contender.freq;
leader.num = [contender.num];
}
}
this.mode = (leader.freq > 1) ? leader.num : [];
// range (float)
this.range = arr[arr.length - 1] - arr[0];
} // end dataset object setter
} // end avg object
try {
// call setter to populate object properties
avg.dataset =...