-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
97 lines (87 loc) · 2.03 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
var Heap = require('heap')
function signum (a, b) {
if (a === b) return 0
return a < b ? -1 : 1
}
function average (a, b) {
return (a + b) / 2
}
module.exports = function () {
// Initial median value
var value = 0
var n = 0
// Right, Min heap
var rHeap = new Heap(function (a, b) {
return a - b
})
// Left, Max heap
var lHeap = new Heap(function (a, b) {
return b - a
})
var median = function median (x) {
if (!isNaN(x)) {
if (typeof x !== 'number') {
x = parseFloat(x)
}
n += 1
var sig = signum(lHeap.size(), rHeap.size())
switch (sig) {
// Left heap size > Right heap
case 1:
if (x < value) {
// Target: left heap
rHeap.push(lHeap.pop())
lHeap.push(x)
} else {
// Target: right heap
rHeap.push(x)
}
// Heaps are balanced
value = average(lHeap.top(), rHeap.top())
break
// Same number of elements
case 0:
if (x < value) {
// Target: left heap
lHeap.push(x)
// Left heap is bigger now. Middle-point is top of the left heap
value = lHeap.top()
} else {
// Target: right heap
rHeap.push(x)
value = rHeap.top()
}
break
// Left heap size < Right heap
case -1:
if (x < value) {
// Target: left heap
lHeap.push(x)
} else {
lHeap.push(rHeap.pop())
rHeap.push(x)
}
// Heaps are balanced
value = average(lHeap.top(), rHeap.top())
break
} // *switch
} else if (Array.isArray(x)) {
x.forEach(el => median(el))
}
return value
}
median.fit = function (x) {
median(x)
}
Object.defineProperty(median, 'value', {
get: function () {
return value
}
})
Object.defineProperty(median, 'n', {
get: function () {
return n
}
})
return median
}