1 |
|
2 |
|
3 | var typal = require("./typal").typal;
|
4 |
|
5 | var setMixin = {
|
6 | constructor: function Set_constructor (set, raw) {
|
7 | this._items = [];
|
8 | if (set && set.constructor === Array)
|
9 | this._items = raw ? set: set.slice(0);
|
10 | else if(arguments.length)
|
11 | this._items = [].slice.call(arguments,0);
|
12 | },
|
13 | concat: function concat (setB) {
|
14 | this._items.push.apply(this._items, setB._items || setB);
|
15 | return this;
|
16 | },
|
17 | eq: function eq (set) {
|
18 | return this._items.length === set._items.length && this.subset(set);
|
19 | },
|
20 | indexOf: function indexOf (item) {
|
21 | if(item && item.eq) {
|
22 | for(var k=0; k<this._items.length;k++)
|
23 | if(item.eq(this._items[k]))
|
24 | return k;
|
25 | return -1;
|
26 | }
|
27 | return this._items.indexOf(item);
|
28 | },
|
29 | union: function union (set) {
|
30 | return (new Set(this._items)).concat(this.complement(set));
|
31 | },
|
32 | intersection: function intersection (set) {
|
33 | return this.filter(function (elm) {
|
34 | return set.contains(elm);
|
35 | });
|
36 | },
|
37 | complement: function complement (set) {
|
38 | var that = this;
|
39 | return set.filter(function sub_complement (elm) {
|
40 | return !that.contains(elm);
|
41 | });
|
42 | },
|
43 | subset: function subset (set) {
|
44 | var cont = true;
|
45 | for (var i=0; i<this._items.length && cont;i++) {
|
46 | cont = cont && set.contains(this._items[i]);
|
47 | }
|
48 | return cont;
|
49 | },
|
50 | superset: function superset (set) {
|
51 | return set.subset(this);
|
52 | },
|
53 | joinSet: function joinSet (set) {
|
54 | return this.concat(this.complement(set));
|
55 | },
|
56 | contains: function contains (item) { return this.indexOf(item) !== -1; },
|
57 | item: function item (v, val) { return this._items[v]; },
|
58 | i: function i (v, val) { return this._items[v]; },
|
59 | first: function first () { return this._items[0]; },
|
60 | last: function last () { return this._items[this._items.length-1]; },
|
61 | size: function size () { return this._items.length; },
|
62 | isEmpty: function isEmpty () { return this._items.length === 0; },
|
63 | copy: function copy () { return new Set(this._items); },
|
64 | toString: function toString () { return this._items.toString(); }
|
65 | };
|
66 |
|
67 | "push shift unshift forEach some every join sort".split(' ').forEach(function (e,i) {
|
68 | setMixin[e] = function () { return Array.prototype[e].apply(this._items, arguments); };
|
69 | setMixin[e].name = e;
|
70 | });
|
71 | "filter slice map".split(' ').forEach(function (e,i) {
|
72 | setMixin[e] = function () { return new Set(Array.prototype[e].apply(this._items, arguments), true); };
|
73 | setMixin[e].name = e;
|
74 | });
|
75 |
|
76 | var Set = typal.construct(setMixin).mix({
|
77 | union: function (a, b) {
|
78 | var ar = {};
|
79 | for (var k=a.length-1;k >=0;--k) {
|
80 | ar[a[k]] = true;
|
81 | }
|
82 | for (var i=b.length-1;i >= 0;--i) {
|
83 | if (!ar[b[i]]) {
|
84 | a.push(b[i]);
|
85 | }
|
86 | }
|
87 | return a;
|
88 | }
|
89 | });
|
90 |
|
91 | if (typeof exports !== 'undefined')
|
92 | exports.Set = Set;
|
93 |
|