Skip to content

Commit 403c975

Browse files
authored
Use object literals instead of switch statements in some constructors (#908)
1 parent 9b5d57d commit 403c975

37 files changed

+386
-489
lines changed

lib/model/agglomerative.js

+7-11
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
const metrics = {
2+
euclid: (a, b) => Math.sqrt(a.reduce((s, v, i) => s + (v - b[i]) ** 2, 0)),
3+
manhattan: (a, b) => a.reduce((s, v, i) => s + Math.abs(v - b[i]), 0),
4+
chebyshev: (a, b) => a.reduce((s, v, i) => Math.max(s, Math.abs(v - b[i])), -Infinity),
5+
}
6+
17
/**
28
* @typedef {object} AgglomerativeClusterNode
39
* @property {number[]} [point] Data point of leaf node
@@ -22,17 +28,7 @@ class AgglomerativeClustering {
2228
if (typeof this._metric === 'function') {
2329
this._d = this._metric
2430
} else {
25-
switch (this._metric) {
26-
case 'euclid':
27-
this._d = (a, b) => Math.sqrt(a.reduce((s, v, i) => s + (v - b[i]) ** 2, 0))
28-
break
29-
case 'manhattan':
30-
this._d = (a, b) => a.reduce((s, v, i) => s + Math.abs(v - b[i]), 0)
31-
break
32-
case 'chebyshev':
33-
this._d = (a, b) => a.reduce((s, v, i) => Math.max(s, Math.abs(v - b[i])), -Infinity)
34-
break
35-
}
31+
this._d = metrics[this._metric]
3632
}
3733
}
3834

lib/model/bogd.js

+12-11
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,14 @@
1+
const kernels = {
2+
gaussian:
3+
({ s = 1 }) =>
4+
(a, b) =>
5+
Math.exp(-(a.reduce((s, v, i) => s + (v - b[i]) ** 2, 0) ** 2) / s ** 2),
6+
polynomial:
7+
({ d = 2 }) =>
8+
(a, b) =>
9+
(1 + a.reduce((s, v, i) => s + v * b[i])) ** d,
10+
}
11+
112
/**
213
* Bounded Online Gradient Descent
314
*/
@@ -34,17 +45,7 @@ export default class BOGD {
3445
if (typeof kernel === 'string') {
3546
kernel = { name: kernel }
3647
}
37-
switch (kernel.name) {
38-
case 'gaussian':
39-
this._s = kernel.s ?? 1
40-
this._kernel = (a, b) =>
41-
Math.exp(-(a.reduce((s, v, i) => s + (v - b[i]) ** 2, 0) ** 2) / this._s ** 2)
42-
break
43-
case 'polynomial':
44-
this._d = kernel.d ?? 2
45-
this._kernel = (a, b) => (1 + a.reduce((s, v, i) => s + v * b[i])) ** this._d
46-
break
47-
}
48+
this._kernel = kernels[kernel.name](kernel)
4849
}
4950

5051
if (loss === 'zero_one') {

lib/model/bpa.js

+12-11
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,16 @@
11
import Matrix from '../util/matrix.js'
22

3+
const kernels = {
4+
gaussian:
5+
({ s = 1 }) =>
6+
(a, b) =>
7+
Math.exp(-(a.reduce((s, v, i) => s + (v - b[i]) ** 2, 0) ** 2) / s ** 2),
8+
polynomial:
9+
({ d = 2 }) =>
10+
(a, b) =>
11+
(1 + a.reduce((s, v, i) => s + v * b[i])) ** d,
12+
}
13+
314
/**
415
* Budgeted online Passive-Aggressive
516
*/
@@ -22,17 +33,7 @@ export default class BPA {
2233
if (typeof kernel === 'string') {
2334
kernel = { name: kernel }
2435
}
25-
switch (kernel.name) {
26-
case 'gaussian':
27-
this._s = kernel.s ?? 1
28-
this._kernel = (a, b) =>
29-
Math.exp(-(a.reduce((s, v, i) => s + (v - b[i]) ** 2, 0) ** 2) / this._s ** 2)
30-
break
31-
case 'polynomial':
32-
this._d = kernel.d ?? 2
33-
this._kernel = (a, b) => (1 + a.reduce((s, v, i) => s + v * b[i])) ** this._d
34-
break
35-
}
36+
this._kernel = kernels[kernel.name](kernel)
3637
}
3738

3839
this._sv = []

lib/model/bsgd.js

+13-22
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,16 @@
11
import Matrix from '../util/matrix.js'
22

3+
const kernels = {
4+
gaussian:
5+
({ s = 1 }) =>
6+
(a, b) =>
7+
Math.exp(-(a.reduce((s, v, i) => s + (v - b[i]) ** 2, 0) ** 2) / s ** 2),
8+
polynomial:
9+
({ d = 2 }) =>
10+
(a, b) =>
11+
(1 + a.reduce((s, v, i) => s + v * b[i])) ** d,
12+
}
13+
314
/**
415
* Budgeted Stochastic Gradient Descent
516
*/
@@ -24,17 +35,7 @@ export default class BSGD {
2435
if (typeof kernel === 'string') {
2536
kernel = { name: kernel }
2637
}
27-
switch (kernel.name) {
28-
case 'gaussian':
29-
this._s = kernel.s ?? 1
30-
this._kernel = (a, b) =>
31-
Math.exp(-(a.reduce((s, v, i) => s + (v - b[i]) ** 2, 0) ** 2) / this._s ** 2)
32-
break
33-
case 'polynomial':
34-
this._d = kernel.d ?? 2
35-
this._kernel = (a, b) => (1 + a.reduce((s, v, i) => s + v * b[i])) ** this._d
36-
break
37-
}
38+
this._kernel = kernels[kernel.name](kernel)
3839
}
3940

4041
this._sv = []
@@ -209,17 +210,7 @@ export class MulticlassBSGD {
209210
if (typeof kernel === 'string') {
210211
kernel = { name: kernel }
211212
}
212-
switch (kernel.name) {
213-
case 'gaussian':
214-
this._s = kernel.s ?? 1
215-
this._kernel = (a, b) =>
216-
Math.exp(-(a.reduce((s, v, i) => s + (v - b[i]) ** 2, 0) ** 2) / this._s ** 2)
217-
break
218-
case 'polynomial':
219-
this._d = kernel.d ?? 2
220-
this._kernel = (a, b) => (1 + a.reduce((s, v, i) => s + v * b[i])) ** this._d
221-
break
222-
}
213+
this._kernel = kernels[kernel.name](kernel)
223214
}
224215

225216
this._classes = []

lib/model/coll.js

+12-11
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,16 @@
11
import Matrix from '../util/matrix.js'
22

3+
const kernels = {
4+
gaussian:
5+
({ s = 1 }) =>
6+
(a, b) =>
7+
Math.exp(-(a.reduce((s, v, i) => s + (v - b[i]) ** 2, 0) ** 2) / s ** 2),
8+
polynomial:
9+
({ d = 2 }) =>
10+
(a, b) =>
11+
(1 + a.reduce((s, v, i) => s + v * b[i])) ** d,
12+
}
13+
314
/**
415
* Conscience on-line learning
516
*/
@@ -20,17 +31,7 @@ export default class COLL {
2031
if (typeof kernel === 'string') {
2132
kernel = { name: kernel }
2233
}
23-
switch (kernel.name) {
24-
case 'gaussian':
25-
this._s = kernel.s ?? 1
26-
this._kernel = (a, b) =>
27-
Math.exp(-(a.reduce((s, v, i) => s + (v - b[i]) ** 2, 0) ** 2) / this._s ** 2)
28-
break
29-
case 'polynomial':
30-
this._d = kernel.d ?? 2
31-
this._kernel = (a, b) => (1 + a.reduce((s, v, i) => s + v * b[i])) ** this._d
32-
break
33-
}
34+
this._kernel = kernels[kernel.name](kernel)
3435
}
3536
}
3637

lib/model/dbscan.js

+7-11
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
const metrics = {
2+
euclid: (a, b) => Math.sqrt(a.reduce((s, v, i) => s + (v - b[i]) ** 2, 0)),
3+
manhattan: (a, b) => a.reduce((s, v, i) => s + Math.abs(v - b[i]), 0),
4+
chebyshev: (a, b) => Math.max(...a.map((v, i) => Math.abs(v - b[i]))),
5+
}
6+
17
/**
28
* Density-based spatial clustering of applications with noise
39
*/
@@ -16,17 +22,7 @@ export default class DBSCAN {
1622
if (typeof this._metric === 'function') {
1723
this._d = this._metric
1824
} else {
19-
switch (this._metric) {
20-
case 'euclid':
21-
this._d = (a, b) => Math.sqrt(a.reduce((s, v, i) => s + (v - b[i]) ** 2, 0))
22-
break
23-
case 'manhattan':
24-
this._d = (a, b) => a.reduce((s, v, i) => s + Math.abs(v - b[i]), 0)
25-
break
26-
case 'chebyshev':
27-
this._d = (a, b) => Math.max(...a.map((v, i) => Math.abs(v - b[i])))
28-
break
29-
}
25+
this._d = metrics[this._metric]
3026
}
3127
}
3228

lib/model/denclue.js

+8-4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
const kernels = {
2+
gaussian: u => {
3+
const d = u.length
4+
return Math.exp(-u.reduce((s, v) => s + v ** 2, 0) / 2) / (2 * Math.PI) ** (d / 2)
5+
},
6+
}
7+
18
/**
29
* DENsity CLUstering
310
*/
@@ -20,10 +27,7 @@ export default class DENCLUE {
2027
if (typeof kernel === 'function') {
2128
this._kernel = kernel
2229
} else if (kernel === 'gaussian' || kernel.name === 'gaussian') {
23-
this._kernel = u => {
24-
const d = u.length
25-
return Math.exp(-u.reduce((s, v) => s + v ** 2, 0) / 2) / (2 * Math.PI) ** (d / 2)
26-
}
30+
this._kernel = kernels.gaussian
2731
}
2832
}
2933

lib/model/diffusion_map.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
import Matrix from '../util/matrix.js'
22

3+
const kernels = {
4+
gaussian: (x, y) => Math.exp(-x.reduce((s, v, i) => s + (v - y[i]) ** 2, 0) / 2),
5+
}
6+
37
/**
48
* Diffusion map
59
*/
@@ -17,7 +21,7 @@ export default class DiffusionMap {
1721
if (typeof kernel === 'function') {
1822
this._k = kernel
1923
} else if (kernel === 'gaussian' || kernel.name === 'gaussian') {
20-
this._k = (x, y) => Math.exp(-x.reduce((s, v, i) => s + (v - y[i]) ** 2, 0) / 2)
24+
this._k = kernels.gaussian
2125
}
2226
}
2327

lib/model/enan.js

+14-19
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,16 @@
1+
const metrics = {
2+
euclid: () => (a, b) => Math.sqrt(a.reduce((s, v, i) => s + (v - b[i]) ** 2, 0)),
3+
manhattan: () => (a, b) => a.reduce((s, v, i) => s + Math.abs(v - b[i]), 0),
4+
chebyshev: () => (a, b) => Math.max(...a.map((v, i) => Math.abs(v - b[i]))),
5+
minkowski:
6+
({ p = 2 } = {}) =>
7+
(a, b) =>
8+
Math.pow(
9+
a.reduce((s, v, i) => s + (v - b[i]) ** p, 0),
10+
1 / p
11+
),
12+
}
13+
114
/**
215
* Extended Natural Neighbor
316
*/
@@ -15,25 +28,7 @@ export default class ENaN {
1528
if (typeof this._metric === 'function') {
1629
this._d = this._metric
1730
} else {
18-
switch (this._metric) {
19-
case 'euclid':
20-
this._d = (a, b) => Math.sqrt(a.reduce((s, v, i) => s + (v - b[i]) ** 2, 0))
21-
break
22-
case 'manhattan':
23-
this._d = (a, b) => a.reduce((s, v, i) => s + Math.abs(v - b[i]), 0)
24-
break
25-
case 'chebyshev':
26-
this._d = (a, b) => Math.max(...a.map((v, i) => Math.abs(v - b[i])))
27-
break
28-
case 'minkowski':
29-
this._dp = 2
30-
this._d = (a, b) =>
31-
Math.pow(
32-
a.reduce((s, v, i) => s + (v - b[i]) ** this._dp, 0),
33-
1 / this._dp
34-
)
35-
break
36-
}
31+
this._d = metrics[this._metric]()
3732
}
3833
}
3934

lib/model/enn.js

+14-19
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,16 @@
1+
const metrics = {
2+
euclid: () => (a, b) => Math.sqrt(a.reduce((s, v, i) => s + (v - b[i]) ** 2, 0)),
3+
manhattan: () => (a, b) => a.reduce((s, v, i) => s + Math.abs(v - b[i]), 0),
4+
chebyshev: () => (a, b) => Math.max(...a.map((v, i) => Math.abs(v - b[i]))),
5+
minkowski:
6+
({ p = 2 } = {}) =>
7+
(a, b) =>
8+
Math.pow(
9+
a.reduce((s, v, i) => s + (v - b[i]) ** p, 0),
10+
1 / p
11+
),
12+
}
13+
114
/**
215
* Extended Nearest Neighbor
316
*/
@@ -18,25 +31,7 @@ export default class ENN {
1831
if (typeof this._metric === 'function') {
1932
this._d = this._metric
2033
} else {
21-
switch (this._metric) {
22-
case 'euclid':
23-
this._d = (a, b) => Math.sqrt(a.reduce((s, v, i) => s + (v - b[i]) ** 2, 0))
24-
break
25-
case 'manhattan':
26-
this._d = (a, b) => a.reduce((s, v, i) => s + Math.abs(v - b[i]), 0)
27-
break
28-
case 'chebyshev':
29-
this._d = (a, b) => Math.max(...a.map((v, i) => Math.abs(v - b[i])))
30-
break
31-
case 'minkowski':
32-
this._dp = 2
33-
this._d = (a, b) =>
34-
Math.pow(
35-
a.reduce((s, v, i) => s + (v - b[i]) ** this._dp, 0),
36-
1 / this._dp
37-
)
38-
break
39-
}
34+
this._d = metrics[this._metric]()
4035
}
4136
}
4237

lib/model/forgetron.js

+12-11
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,14 @@
1+
const kernels = {
2+
gaussian:
3+
({ s = 1 }) =>
4+
(a, b) =>
5+
Math.exp(-(a.reduce((s, v, i) => s + (v - b[i]) ** 2, 0) ** 2) / s ** 2),
6+
polynomial:
7+
({ d = 2 }) =>
8+
(a, b) =>
9+
(1 + a.reduce((s, v, i) => s + v * b[i])) ** d,
10+
}
11+
112
/**
213
* Forgetron
314
*/
@@ -19,17 +30,7 @@ export default class Forgetron {
1930
if (typeof kernel === 'string') {
2031
kernel = { name: kernel }
2132
}
22-
switch (kernel.name) {
23-
case 'gaussian':
24-
this._s = kernel.s ?? 1
25-
this._kernel = (a, b) =>
26-
Math.exp(-(a.reduce((s, v, i) => s + (v - b[i]) ** 2, 0) ** 2) / this._s ** 2)
27-
break
28-
case 'polynomial':
29-
this._d = kernel.d ?? 2
30-
this._kernel = (a, b) => (1 + a.reduce((s, v, i) => s + v * b[i])) ** this._d
31-
break
32-
}
33+
this._kernel = kernels[kernel.name](kernel)
3334
}
3435

3536
this._i = []

0 commit comments

Comments
 (0)