using System; using System.Collections.Generic; using System.Linq; namespace ln.collections { public class BTreeValueSet { public bool Empty => bTree.Empty; 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); } } }