176 lines
4.6 KiB
C#
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();
|
|
}
|
|
}
|
|
}
|