Skip to content

Commit bdc926d

Browse files
committed
First Set Commit
First Set Commit as an example of most changes currently proposed in numbers#80.
1 parent e19eb49 commit bdc926d

File tree

3 files changed

+361
-0
lines changed

3 files changed

+361
-0
lines changed

lib/numbers/create.js

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
var numbers = require('../numbers');
2+
var create = exports;
3+
4+
create.Set = function(data) {
5+
var s = new Set();
6+
return s.add(data);
7+
};

lib/types/set.js

+354
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,354 @@
1+
var numbers = require('../numbers'),
2+
exports = Set;
3+
4+
//TODO Determine where _getValid and _getValidElement can go.
5+
/**
6+
* Get the information in a valid form according to the {Set} API.
7+
*
8+
* @param {Array|Number} Data or set of elements
9+
* @param {Object} object to determine which test.
10+
*/
11+
function _getValid(data, obj) {
12+
if (Set.prototype.isPrototypeOf(obj)) {
13+
if (Object.prototype.toString.call(data) === '[object Array]') {
14+
return data; //TODO map getValidElement.
15+
} else {
16+
return [data];
17+
}
18+
}
19+
else {
20+
throw new Error(obj.constructor + " is currently not supported in _getValid.");
21+
}
22+
}
23+
24+
/**
25+
* Get the elements in a valid form according to the {Set} API.
26+
*
27+
* @param {Array|Number} Element
28+
* @param {Object} object to determine which test.
29+
*/
30+
function _getValidElement(d, obj) {
31+
if (Set.prototype.isPrototypeOf(obj)) {
32+
// currently only support numbers
33+
// If hashing is implemented, it should be hashed here and rehashed in toArray
34+
if (d % 1 === 0) return ''+d;
35+
else throw new Error(d + " is not a valid element for a Set");
36+
}
37+
else {
38+
throw new Error(obj.constructor + " is currently not supported in _getValidElement.");
39+
}
40+
}
41+
42+
/**
43+
* Core Data Structure for use in numbers.js library.
44+
* This data structure implements a set (with similar API to
45+
* that of python's set data structure).
46+
*
47+
* @param {Number|Array} (optional) values to add to initial Set object.
48+
*/
49+
var Set = function(data) {
50+
if (arguments.length === 0) {
51+
this.data = {};
52+
}
53+
else {
54+
data = _getValid(data, this); //returns array
55+
this.data = {};
56+
var l = this.length,
57+
i;
58+
for (i = 0; i < l; i++) {
59+
this.add(data[i]);
60+
}
61+
}
62+
};
63+
64+
/**
65+
* Determine if the Set has value(s).
66+
*
67+
* @param {Number|Array} Value(s) added to set
68+
* @return {Boolean|Array} Returns a boolean array or boolean value
69+
*/
70+
Set.prototype.has = function(d) {
71+
if (Object.prototype.toString.call(d) === '[object Array]') {
72+
var i,
73+
l = d.length,
74+
ret = [];
75+
for (i = 0; i < l; i++) {
76+
ret.push(this.has(d[i]));
77+
}
78+
return ret;
79+
}
80+
else {
81+
d = _getValidElement(d, this);
82+
return this.data.hasOwnProperty(d);
83+
}
84+
};
85+
86+
/**
87+
* Create a copy of the Set.
88+
*
89+
* @return {Set} an exact copy of this set.
90+
*/
91+
Set.prototype.clone = function() {
92+
return new Set(this.toArray()); //TODO proper copy
93+
};
94+
95+
/**
96+
* Determine if all values in B are in this set.
97+
*
98+
* @param {Set|Array} Set B or array to create set from
99+
* @return {Boolean} true for superset
100+
*/
101+
Set.prototype.isSuperSet = function(B) {
102+
if (!Set.prototype.isPrototypeOf(B))
103+
B = new Set(_getValid(B, this));
104+
return this.has(B.toArray()).reduce(function(a, b) {
105+
return !!a && !!b;
106+
});
107+
};
108+
109+
/**
110+
* Determine if all values in this set are in B.
111+
*
112+
* @param {Set|Array} Set B or array to create set from
113+
* @return {}
114+
*/
115+
Set.prototype.isSubSet = function(B) {
116+
if (!Set.prototype.isPrototypeOf(B))
117+
B = new Set(_getValid(B, this));
118+
return B.has(this.toArray()).reduce(function(a, b) {
119+
return !!a && !!b;
120+
});
121+
};
122+
123+
/**
124+
* Convert this Set to an Array
125+
*
126+
* @param {Function} (optional) the function in which to sort the array by
127+
* @return {Array} Array of elements in set.
128+
*/
129+
Set.prototype.toArray = function(sortFunc) {
130+
var ret = Object.keys(this.data);
131+
ret.map(function(a) { return +a; }); //currently supports only numbers
132+
if (arguments.length === 1) ret.sort(sortFunc);
133+
return ret;
134+
};
135+
136+
/**
137+
* Add value(s) to this Set.
138+
* (A + B)
139+
*
140+
* @param {Number|Array} Value(s) added to set
141+
* @return {Set} Updated Set
142+
*/
143+
Set.prototype.add = function(d) {
144+
if (Object.prototype.toString.call(d) === '[object Array]') {
145+
var i,
146+
l = d.length;
147+
for (i = 0; i < l; i++) {
148+
this.add(d[i]);
149+
}
150+
}
151+
else {
152+
d = _getValidElement(d, this);
153+
if (!this.has(d)) {
154+
this.data[d] = true;
155+
this.size++;
156+
}
157+
}
158+
return this;
159+
};
160+
161+
/**
162+
* Remove value(s) from this Set.
163+
* (A - B)
164+
*
165+
* @param {Number|Array} Value(s) removed from set
166+
* @return {Set} Updated Set
167+
*/
168+
Set.prototype.remove = function(d) {
169+
if (Object.prototype.toString.call(d) === '[object Array]') {
170+
var i,
171+
l = d.length,
172+
ret = [];
173+
for (i = 0; i < l; i++) {
174+
ret.push(this.remove(d[i]));
175+
}
176+
return ret;
177+
}
178+
else {
179+
d = _getValidElement(d, this);
180+
if (this.has(d)) {
181+
delete this.data[d];
182+
this.size--;
183+
return true;
184+
}
185+
return false;
186+
}
187+
};
188+
189+
/**
190+
* Add any elements from B that are not already in A.
191+
* (A | B)
192+
*
193+
* @param {Set|Array} the set or data to create a set from
194+
* @return {Set} Updated Set
195+
*/
196+
Set.prototype.union = function(B) {
197+
if (!Set.prototype.isPrototypeOf(B))
198+
B = new Set(_getValid(B, this));
199+
return this.add(B.toArray());
200+
};
201+
202+
/**
203+
* Creates an updated set containing elements which are both in this and in B.
204+
* (A & B)
205+
*
206+
* @param {Set|Array} the set or data to create a set from
207+
* @return {Set} Updated Set
208+
*/
209+
Set.prototype.intersection = function(B) {
210+
if (!Set.prototype.isPrototypeOf(B))
211+
B = new Set(_getValid(B, this));
212+
var BList = B.toArray(),
213+
check = this.has(BList),
214+
i,
215+
l = BList.length,
216+
commonList = [];
217+
for (i = 0; i < l; i++) {
218+
if (check[i])
219+
commonList.push(BList[i]);
220+
}
221+
this = new Set(commonList);
222+
return this;
223+
};
224+
225+
/**
226+
* Removes all elements in this set that are also in set B.
227+
* (A - B)
228+
*
229+
* @param {Set|Array} the set or data to create a set from
230+
* @return {Set} Updated Set
231+
*/
232+
Set.prototype.difference = function(B) {
233+
if (!Set.prototype.isPrototypeOf(B))
234+
B = new Set(_getValid(B, this));
235+
var AList = this.toArray(),
236+
check = B.has(AList), //TODO all should also accept sets
237+
i,
238+
l = AList.length,
239+
differenceList = [];
240+
for (i = 0; i < l; i++) {
241+
if (!check[i])
242+
differenceList.push(AList[i]);
243+
}
244+
//TODO not right
245+
this = new Set(differenceList);
246+
return this;
247+
};
248+
249+
/**
250+
* Update set to only include elements not in A and not in B.
251+
* (A | B) - (A & B)
252+
* A + B - (A & B)
253+
*
254+
* @param {Set|Array} the set or data to create a set from
255+
* @return {Set} Updated Set
256+
*/
257+
Set.prototype.symmetricDifference = function(B) {
258+
if (!Set.prototype.isPrototypeOf(B))
259+
B = new Set(_getValid(B, this));
260+
var BAdded = B.difference(this.clone()
261+
.intersection(B))
262+
.toArray(); //needs to accept sets
263+
this.difference(this.clone()
264+
.intersection(B));
265+
return this.add(BAdded);
266+
};
267+
268+
/**
269+
* Non-modified static wrapper of Set.prototype.add()
270+
*
271+
* @param {Set|Array} the set or data to create a set from
272+
* @param {Number|Array} values to add to the set.
273+
* @return {Set} A copy or created Set with updates made.
274+
*/
275+
Set.add = function(A, d) {
276+
if (!Set.prototype.isPrototypeOf(A))
277+
A = new Set(_getValid(A, this));
278+
return A.clone()
279+
.add(d);
280+
};
281+
282+
/**
283+
* Non-modified static wrapper of Set.prototype.remove()
284+
*
285+
* @param {Set|Array} the set or data to create a set from
286+
* @param {Number|Array} values to add to the set.
287+
* @return {Set} A copy or created Set with updates made.
288+
*/
289+
Set.remove = function(A, d) {
290+
if (!Set.prototype.isPrototypeOf(A))
291+
A = new Set(_getValid(A, this));
292+
var newA = A.clone(),
293+
newA.remove(d);
294+
return newA;
295+
};
296+
297+
/**
298+
* Non-modified static wrapper of Set.prototype.union()
299+
*
300+
* @param {Set|Array} the set or data to create a set from
301+
* @param {Set|Array} the set to union with A, or data to create set from
302+
* @return {Set} A copy or created Set with updates made.
303+
*/
304+
Set.union = function(A, B) {
305+
if (!Set.prototype.isPrototypeOf(A))
306+
A = new Set(_getValid(A, this));
307+
return A.clone()
308+
.union(B);
309+
};
310+
311+
/**
312+
* Non-modified static wrapper of Set.prototype.intersection()
313+
*
314+
* @param {Set|Array} the set or data to create a set from
315+
* @param {Set|Array} the set to union with A, or data to create set from
316+
* @return {Set} A copy or created Set with updates made.
317+
*/
318+
Set.intersection = function(A, B) {
319+
if (!Set.prototype.isPrototypeOf(A))
320+
A = new Set(_getValid(A, this));
321+
return A.clone()
322+
.intersection(B);
323+
};
324+
325+
/**
326+
* Non-modified static wrapper of Set.prototype.union()
327+
*
328+
* @param {Set|Array} the set or data to create a set from
329+
* @param {Set|Array} the set to union with A, or data to create set from
330+
* @return {Set} A copy or created Set with updates made.
331+
*/
332+
Set.difference = function(A, B) {
333+
if (!Set.prototype.isPrototypeOf(A))
334+
A = new Set(_getValid(A, this));
335+
return A.clone()
336+
.difference(B);
337+
};
338+
339+
/**
340+
* Non-modified static wrapper of Set.prototype.union()
341+
*
342+
* @param {Set|Array} the set or data to create a set from
343+
* @param {Set|Array} the set to union with A, or data to create set from
344+
* @return {Set} A copy or created Set with updates made.
345+
*/
346+
347+
348+
349+
Set.symmetricDifference = function(A, B) {
350+
if (!Set.prototype.isPrototypeOf(A))
351+
A = new Set(_getValid(A, this));
352+
return A.clone()
353+
.symmetricDifference(B);
354+
};

test/set.test.js

Whitespace-only changes.

0 commit comments

Comments
 (0)