Browse Source

Set attempt #1

Billy Barrow 1 month ago
parent
commit
3ed4709a5e
1 changed files with 52 additions and 12 deletions
  1. 52 12
      src/lib/Collections/Set.vala

+ 52 - 12
src/lib/Collections/Set.vala

@@ -4,7 +4,8 @@ namespace Invercargill {
 
 
     public class Set<T> : Collection<T> {
     public class Set<T> : Collection<T> {
 
 
-        private Dictionary<T, T> dict;
+        private Vector<T> items;
+        private Vector<Series<int>> buckets;
         private HashDelegate<T> hash_func;
         private HashDelegate<T> hash_func;
         private EqualityDelegate<T> equal_func;
         private EqualityDelegate<T> equal_func;
 
 
@@ -17,18 +18,32 @@ namespace Invercargill {
         }
         }
 
 
         private void setup(HashDelegate<T>? value_hash_func = null, EqualityDelegate<T>? value_equal_func = null) {
         private void setup(HashDelegate<T>? value_hash_func = null, EqualityDelegate<T>? value_equal_func = null) {
-            hash_func = value_hash_func;
-            equal_func = value_equal_func;
-            dict = new Dictionary<T, T>(value_hash_func, value_equal_func);
+            hash_func = value_hash_func ?? Operators.hash<T>();
+            equal_func = value_equal_func ?? Operators.equality<T>();
+            items = new Vector<T>();
+            buckets = new Vector<Series<int>>();
+            buckets.add_all(range(0, 4096).select<Series<int>>(i => new Series<int>()));
         }
         }
 
 
 
 
         public override Tracker<T> get_tracker () {
         public override Tracker<T> get_tracker () {
-            return dict.get_keys().get_tracker();
+            return items.get_tracker();
         }
         }
 
 
         public override void add (T item) {
         public override void add (T item) {
-            dict[item] = item;
+            var index = (int)bucket_for(item);
+            var bucket = buckets.get_or_default(index);
+            if(bucket != null && bucket.any(i => equal_func(i, item)))
+                return;
+
+            if(bucket == null) {
+                bucket = new Series<int>();
+                buckets[index] = bucket;
+            }
+
+            var item_index = items.count();
+            items.add(item);
+            bucket.add(item_index);
         }
         }
 
 
         public override void add_all (Enumerable<T> items) {
         public override void add_all (Enumerable<T> items) {
@@ -54,7 +69,17 @@ namespace Invercargill {
         }
         }
 
 
         public new T? find(T item) {
         public new T? find(T item) {
-            return dict.get_or_default(item);
+            var bucket = buckets.get_or_default((int)bucket_for(item));
+            if(bucket == null) 
+                return null;
+
+            foreach (var index in bucket) {
+                var result = items[index];
+                if(equal_func(result, item)) {
+                    return result;
+                }
+            }
+            return null;
         }
         }
 
 
         public override void remove_first_where (Invercargill.PredicateDelegate<T> predicate) {
         public override void remove_first_where (Invercargill.PredicateDelegate<T> predicate) {
@@ -62,26 +87,41 @@ namespace Invercargill {
         }
         }
 
 
         public override void remove_where (Invercargill.PredicateDelegate<T> predicate) {
         public override void remove_where (Invercargill.PredicateDelegate<T> predicate) {
-            dict.remove_where(predicate);
+            items.where(predicate).iterate(remove);
         }
         }
 
 
         public void remove(T item) {
         public void remove(T item) {
-            dict.clear(item);
+            var bucket = buckets.get_or_default((int)bucket_for(item));
+            if(bucket == null) 
+                return;
+
+            foreach (var index in bucket) {
+                var result = items[index];
+                if(equal_func(result, item)) {
+                    bucket.remove_first_where(i => i == index);
+                    items.remove(index);
+                }
+            }
         }
         }
 
 
         public void remove_all(Enumerable<T> items) {
         public void remove_all(Enumerable<T> items) {
-            items.iterate(dict.clear);
+            items.iterate(remove);
         }
         }
 
 
         public void remove_except(Enumerable<T> items) {
         public void remove_except(Enumerable<T> items) {
             var other = items.to_set(hash_func, equal_func);
             var other = items.to_set(hash_func, equal_func);
-            dict.remove_where(i => !other.has(i));
+            remove_where(i => !other.has(i));
         }
         }
 
 
         public bool has(T item) {
         public bool has(T item) {
-            return dict.has(item);
+            var bucket = buckets.get_or_default((int)bucket_for(item));
+            return bucket != null && bucket.any(i => equal_func(i, item));
         }
         }
 
 
+        private uint bucket_for(T item) {
+            var hash = hash_func(item);
+            return hash % buckets.count();
+        }
 
 
     }
     }
 }
 }