using System; using System.Collections; using System.Collections.Generic; using System.Linq; namespace InABox.Core { public interface IMutableLookup : ILookup { void Add(TKey key, TElement element); void AddRange(TKey key, IEnumerable elements); void Remove(TKey key); } public class MutableLookup : IMutableLookup { private readonly Dictionary> _data = new Dictionary>(); public MutableLookup() { } public MutableLookup(ILookup source) { foreach (var grouping in source) foreach (var element in grouping) Add(grouping.Key, element); } public IEnumerable All => (from key in _data.Keys select _data[key]) .SelectMany(list => list); public int Count => All.Count(); public IEnumerable this[TKey key] { get { List result; if (_data.TryGetValue(key, out result)) return result; return Array.Empty(); } } public bool Contains(TKey key) { return _data.ContainsKey(key); } public void Add(TKey key, TElement element) { if (!_data.TryGetValue(key, out var list)) { list = new List(); _data.Add(key, list); } if (!list.Contains(element)) list.Add(element); } public void AddRange(TKey key, IEnumerable elements) { if (!_data.TryGetValue(key, out var list)) { list = new List(); _data.Add(key, list); } list.AddRange(elements.Where(x => list.Contains(x))); } public void Remove(TKey key) { _data.Remove(key); } public IEnumerator> GetEnumerator() { return GetGroupings().GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return (GetGroupings() as IEnumerable).GetEnumerator(); } private IEnumerable> GetGroupings() { return from key in _data.Keys select new LookupDictionaryGrouping { Key = key, Elements = _data[key] } as IGrouping; } } public class LookupDictionaryGrouping : IGrouping { public IEnumerable Elements { get; set; } public TKey Key { get; set; } public IEnumerator GetEnumerator() { return Elements.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return (Elements as IEnumerable).GetEnumerator(); } } }