ln.collections/ln.collections/BTreeValueSet.cs

176 lines
4.6 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
namespace ln.collections
{
public class BTreeValueSet<K, V> : IEnumerable<KeyValuePair<K, V>>
{
public bool Empty => bTree.Empty;
public Comparison<K> Comparison => bTree.Comparison;
BTree<K, HashSet<V>> bTree;
public BTreeValueSet()
{
bTree = new BTree<K, HashSet<V>>();
}
public BTreeValueSet(Comparison<K> comparison)
{
bTree = new BTree<K, HashSet<V>>(comparison);
}
public IEnumerable<V> this[K key]
{
get
{
if (TryGet(key, out IEnumerable<V> 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<V> values))
{
values = new HashSet<V>();
bTree.Add(key, values);
}
return values.Add(value);
}
public bool TryGet(K key, out IEnumerable<V> values)
{
if ((!bTree.TryGet(key, out HashSet<V> 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<V> 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<V> _values))
return false;
return _values.Count > 0;
}
public bool ContainsValue(V value)
{
foreach (HashSet<V> _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<V> _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<K> Keys => bTree.Keys;
public IEnumerable<V> Values => bTree.Values.SelectMany(vl => vl);
public IEnumerable<KeyValuePair<K, V>> GetKeyValuePairs()
{
foreach (K key in Keys)
{
HashSet<V> lv = bTree[key];
foreach (V value in lv)
yield return new KeyValuePair<K, V>(key, value);
}
}
public void AddRange(IEnumerable<KeyValuePair<K, V>> keyValuePairs)
{
foreach (KeyValuePair<K, V> keyValuePair in keyValuePairs)
Add(keyValuePair.Key, keyValuePair.Value);
}
public IEnumerable<KeyValuePair<K, V>> GetInterval(K start, K end) => GetInterval(start, end, null);
public IEnumerable<KeyValuePair<K, V>> GetInterval(K start, K end, Func<K,V,bool> filter)
{
foreach (KeyValuePair<K, HashSet<V>> 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<K, V>(vl.Key, v);
}
}
public IEnumerator<KeyValuePair<K, V>> GetEnumerator()
{
foreach (KeyValuePair<K, HashSet<V>> vl in this.bTree)
foreach (V v in vl.Value)
{
yield return new KeyValuePair<K, V>(vl.Key, v);
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
}