Set.vala 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. using Invercargill.Convert;
  2. namespace Invercargill {
  3. public class Set<T> : Collection<T> {
  4. private Vector<T> items;
  5. private Vector<Series<int>> buckets;
  6. private HashDelegate<T> hash_func;
  7. private EqualityDelegate<T> equal_func;
  8. construct {
  9. setup();
  10. }
  11. public Set(HashDelegate<T>? value_hash_func = null, EqualityDelegate<T>? value_equal_func = null) {
  12. setup(value_hash_func, value_equal_func);
  13. }
  14. private void setup(HashDelegate<T>? value_hash_func = null, EqualityDelegate<T>? value_equal_func = null) {
  15. hash_func = value_hash_func ?? Operators.hash<T>();
  16. equal_func = value_equal_func ?? Operators.equality<T>();
  17. items = new Vector<T>();
  18. buckets = new Vector<Series<int>>();
  19. buckets.add_all(range(0, 4096).select<Series<int>>(i => new Series<int>()));
  20. }
  21. public override Tracker<T> get_tracker () {
  22. return items.get_tracker();
  23. }
  24. public override void add (T item) {
  25. var index = (int)bucket_for(item);
  26. var bucket = buckets.get_or_default(index);
  27. if(bucket != null && bucket.any(i => equal_func(i, item)))
  28. return;
  29. if(bucket == null) {
  30. bucket = new Series<int>();
  31. buckets[index] = bucket;
  32. }
  33. var item_index = items.count();
  34. items.add(item);
  35. bucket.add(item_index);
  36. }
  37. public override void add_all (Enumerable<T> items) {
  38. items.iterate(add);
  39. }
  40. public Set<T> union(Enumerable<T> items) {
  41. var new_set = to_set (hash_func, equal_func);
  42. new_set.add_all (items);
  43. return new_set;
  44. }
  45. public Set<T> difference(Enumerable<T> items) {
  46. var new_set = to_set (hash_func, equal_func);
  47. new_set.remove_all(items);
  48. return new_set;
  49. }
  50. public Set<T> intersection(Enumerable<T> items) {
  51. var new_set = to_set (hash_func, equal_func);
  52. new_set.remove_except(items);
  53. return new_set;
  54. }
  55. public new T? find(T item) {
  56. var bucket = buckets.get_or_default((int)bucket_for(item));
  57. if(bucket == null)
  58. return null;
  59. foreach (var index in bucket) {
  60. var result = items[index];
  61. if(equal_func(result, item)) {
  62. return result;
  63. }
  64. }
  65. return null;
  66. }
  67. public override void remove_first_where (Invercargill.PredicateDelegate<T> predicate) {
  68. remove(first_or_default(predicate));
  69. }
  70. public override void remove_where (Invercargill.PredicateDelegate<T> predicate) {
  71. items.where(predicate).iterate(remove);
  72. }
  73. public void remove(T item) {
  74. var bucket = buckets.get_or_default((int)bucket_for(item));
  75. if(bucket == null)
  76. return;
  77. foreach (var index in bucket) {
  78. var result = items[index];
  79. if(equal_func(result, item)) {
  80. bucket.remove_first_where(i => i == index);
  81. items.remove(index);
  82. }
  83. }
  84. }
  85. public void remove_all(Enumerable<T> items) {
  86. items.iterate(remove);
  87. }
  88. public void remove_except(Enumerable<T> items) {
  89. var other = items.to_set(hash_func, equal_func);
  90. remove_where(i => !other.has(i));
  91. }
  92. public bool has(T item) {
  93. var bucket = buckets.get_or_default((int)bucket_for(item));
  94. return bucket != null && bucket.any(i => equal_func(i, item));
  95. }
  96. private uint bucket_for(T item) {
  97. var hash = hash_func(item);
  98. return hash % buckets.count();
  99. }
  100. }
  101. }