-
Notifications
You must be signed in to change notification settings - Fork 2
/
set.js
108 lines (84 loc) · 2.2 KB
/
set.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
98
99
100
101
102
103
104
105
106
107
108
class Set {
#set
constructor (elements = []) {
if (!Array.isArray(elements)) throw Error('Invalid set constructor')
this.#set = new Map()
this.#buildList(elements)
}
add (element) {
if (this.has(element)) return false
this.#set.set(element, element)
return true
}
delete (element) {
return this.#set.delete(element)
}
has (element) {
return this.#set.has(element)
}
clear () {
return this.#set.clear()
}
get size () {
return this.#set.size
}
values () {
return [...this]
}
#buildList (elements) {
if (elements.length === 0) return undefined
for (const element of elements) {
this.#set.set(element, element)
}
}
union (otherSet) {
if (!(otherSet instanceof Set)) throw Error('Invalid parameter type')
return new Set([...this, ...otherSet])
}
intersection (otherSet) {
if (!(otherSet instanceof Set)) throw Error('Invalid parameter type')
// finding the smallest number of elements reduces the total number of comparisons
const smallerSet = otherSet.size < this.size ? otherSet : this
const biggerSet = otherSet.size < this.size ? this : otherSet
const newSet = new Set()
for (const element of smallerSet) {
if (biggerSet.has(element)) newSet.add(element)
}
return newSet
}
difference (otherSet) {
if (!(otherSet instanceof Set)) throw Error('Invalid parameter type')
const newSet = new Set(this.values())
if (otherSet.size < newSet.size) {
for (const element of otherSet) {
if (newSet.has(element)) newSet.delete(element)
}
} else {
for (const element of newSet) {
if (otherSet.has(element)) newSet.delete(element)
}
}
return newSet
}
subset (otherSet) {
if (this.size > otherSet.size) return false
for (const element of this) {
if (!otherSet.has(element)) return false
}
return true
}
[Symbol.iterator] () {
const data = this.#set.values()
return {
next: () => {
const { value, done } = data.next()
if (!done) {
return { value, done: false }
} else {
return { done: true }
}
}
}
}
}
export default Set