using System; using System.Collections; using System.Collections.Generic; using System.Linq; namespace ln.collections { public class BTreeValueSet : IEnumerable> { public bool Empty => bTree.Empty; public Comparison Comparison => bTree.Comparison; BTree> bTree; public BTreeValueSet() { bTree = new BTree>(); } public BTreeValueSet(Comparison comparison) { bTree = new BTree>(comparison); } public IEnumerable this[K key] { get { if (TryGet(key, out IEnumerable values)) { return values; } throw new KeyNotFoundException(); } } public void Add(K key, V value) { if (!TryAdd(key, value)) throw new ArgumentException("duplicate key"); } public void Remove(K key, V value) { if (!TryRemove(key, value)) throw new KeyNotFoundException(); } public void Remove(K key) { if (!TryRemove(key)) throw new KeyNotFoundException(); } public bool TryAdd(K key, V value) { if (!bTree.TryGet(key, out HashSet values)) { values = new HashSet(); bTree.Add(key, values); } return values.Add(value); } public bool TryGet(K key, out IEnumerable values) { if ((!bTree.TryGet(key, out HashSet v)) || (v.Count == 0)) { values = v; return false; } values = v; return true; } public bool TryRemove(K key) { return bTree.TryRemove(key); } public bool TryRemove(K key, V value) { if (bTree.TryGet(key, out HashSet values)) { bool success = values.Remove(value); if (values.Count == 0) bTree.Remove(key); return success; } return false; } public bool ContainsKey(K key) { if (!bTree.TryGet(key, out HashSet _values)) return false; return _values.Count > 0; } public bool ContainsValue(V value) { foreach (HashSet _values in bTree.Values) { foreach (V v in _values) if (v.Equals(value)) return true; } return false; } public int Count(K key) { if ((!bTree.TryGet(key, out HashSet _values)) || (_values.Count == 0)) return 0; return _values.Count; } public void Clear() { bTree.Clear(); } public K First => bTree.First(); public K Last => bTree.Last(); public IEnumerable Keys => bTree.Keys; public IEnumerable Values => bTree.Values.SelectMany(vl => vl); public IEnumerable> GetKeyValuePairs() { foreach (K key in Keys) { HashSet lv = bTree[key]; foreach (V value in lv) yield return new KeyValuePair(key, value); } } public void AddRange(IEnumerable> keyValuePairs) { foreach (KeyValuePair keyValuePair in keyValuePairs) Add(keyValuePair.Key, keyValuePair.Value); } public IEnumerable> GetInterval(K start, K end) => GetInterval(start, end, null); public IEnumerable> GetInterval(K start, K end, Func filter) { foreach (KeyValuePair> vl in this.bTree.GetInterval(start, end)) foreach (V v in vl.Value) { if (filter is null || filter(vl.Key, v)) yield return new KeyValuePair(vl.Key, v); } } public IEnumerator> GetEnumerator() { foreach (KeyValuePair> vl in this.bTree) foreach (V v in vl.Value) { yield return new KeyValuePair(vl.Key, v); } } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } }