signalis-eb/godot/addons/collections/set.gd
2025-06-10 22:41:26 -04:00

98 lines
2.5 KiB
GDScript

class_name Set extends BST._Node
var data: Variant
func _init(data: Variant = null) -> void:
super(_get_value(data))
self.data = data
static func _get_value(value: Variant) -> int:
match typeof(value):
TYPE_NIL: return -1
TYPE_INT: return value
_: return hash(value)
static func empty() -> Set:
return Set.new(null)
static func from_iter(iter: Variant) -> Set:
var nodes: Array[_Node] = []
for value in iter:
nodes.append(Set.new(value))
return BST._build_balanced_tree(nodes).unwrap()
static func compare(a: Set, b: Set) -> bool:
return a.data < b.data
func balance() -> Set:
var nodes = BST._store_in_order(Option.some(self))
nodes.sort_custom(compare)
return BST._build_balanced_tree(nodes).unwrap()
func is_empty() -> bool:
return value == -1 and not has_children()
func contains(data: Variant) -> bool:
return BST.search(self, _get_value(data)).is_some()
func insert(data: Variant) -> _Node:
if is_empty():
self.value = _get_value(data)
self.data = data
return self
elif not contains(data):
return BST._insert(Option.some(self), Set.new(data))
else:
return self
func remove(data: Variant) -> Option:
return BST.remove(self, _get_value(data))
func get(data: Variant) -> Option:
return BST.search(self, _get_value(data)).map(func(x: Set) -> Variant: return x.data)
func equals(other: Set) -> bool:
if not size() == other.size(): return false
for value in iter():
if not other.contains(value): return false
return true
func union(other: Set) -> Set:
var u = Set.from_iter(iter())
for value in other.iter():
u.insert(value)
return u.balance()
func intersect(other: Set) -> Set:
var i = Set.empty()
for value in iter():
if other.contains(value):
i.insert(value)
return i.balance()
func difference(other: Set) -> Set:
if self.is_empty(): return Set.empty()
elif other.is_empty(): return Set.from_iter(iter())
var diff = Set.empty()
for value in iter():
if not other.contains(value):
diff.insert(value)
return diff.balance()
static func _iter(_set: Set) -> Iterator:
var iters = Option.collect_some([
_set.left.map(_iter),
Option.none if _set.value == -1 else Option.some(SingletonIterator.new(_set.data)),
_set.right.map(_iter)
], true).unwrap()
var iter_arr: Array[Iterator]
iter_arr.assign(iters)
return FusedIterator.new(iter_arr)
func iter() -> Iterator:
return _iter(self)