Created
August 26, 2020 05:56
-
-
Save YairHalberstadt/1d4d9cf3a831e9227980fefed70e73e6 to your computer and use it in GitHub Desktop.
A Dictionary backed by a list, efficient for small dictionary sizes with quick comparisons
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections; | |
using System.Collections.Generic; | |
using System.Linq; | |
public class ListDictionary<TKey, TValue> : IDictionary<TKey, TValue> | |
{ | |
private readonly List<KeyValuePair<TKey, TValue>> _list; | |
public ListDictionary() | |
{ | |
_list = new List<KeyValuePair<TKey, TValue>>(); | |
} | |
public int Count => _list.Count; | |
bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly => false; | |
public TValue this[TKey key] | |
{ | |
get | |
{ | |
var index = GetIndex(key); | |
if (index < 0) | |
{ | |
throw new KeyNotFoundException(key?.ToString()); | |
} | |
return _list[index].Value; | |
} | |
set | |
{ | |
var index = RemoveAndGetIndex(key); | |
var keyValuePair = new KeyValuePair<TKey, TValue>(key, value); | |
if (index >= 0) | |
{ | |
_list.Insert(index, keyValuePair); | |
} | |
else | |
{ | |
_list.Add(keyValuePair); | |
} | |
} | |
} | |
public IEnumerable<TKey> Keys => _list.Select(item => item.Key); | |
public IEnumerable<TValue> Values => _list.Select(item => item.Value); | |
ICollection<TKey> IDictionary<TKey, TValue>.Keys => Keys.ToList(); | |
ICollection<TValue> IDictionary<TKey, TValue>.Values => Values.ToList(); | |
public List<KeyValuePair<TKey, TValue>>.Enumerator GetEnumerator() => _list.GetEnumerator(); | |
IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator() => GetEnumerator(); | |
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); | |
public void Add(KeyValuePair<TKey, TValue> item) | |
{ | |
if (ContainsKey(item.Key)) | |
{ | |
throw new ArgumentException($"An element with the same key '${item.Key}' already exists"); | |
} | |
_list.Add(item); | |
} | |
public void Clear() => _list.Clear(); | |
public bool Contains(KeyValuePair<TKey, TValue> item) => _list.Contains(item); | |
public bool Remove(KeyValuePair<TKey, TValue> item) => _list.Remove(item); | |
public void Add(TKey key, TValue value) => Add(new KeyValuePair<TKey, TValue>(key, value)); | |
public bool ContainsKey(TKey key) | |
{ | |
var index = GetIndex(key); | |
return index >= 0; | |
} | |
public bool Remove(TKey key) | |
{ | |
var index = RemoveAndGetIndex(key); | |
return index >= 0; | |
} | |
public bool TryGetValue(TKey key, out TValue value) | |
{ | |
var index = GetIndex(key); | |
if (index < 0) | |
{ | |
value = default!; | |
return false; | |
} | |
value = _list[index].Value; | |
return true; | |
} | |
private int RemoveAndGetIndex(TKey key) | |
{ | |
var index = GetIndex(key); | |
if (index >= 0) | |
{ | |
_list.RemoveAt(index); | |
} | |
return index; | |
} | |
private int GetIndex(TKey key) | |
{ | |
for (var index = 0; index < _list.Count; index++) | |
{ | |
var (indexKey, _) = _list[index]; | |
if (EqualityComparer<TKey>.Default.Equals(indexKey, key)) | |
{ | |
return index; | |
} | |
} | |
return -1; | |
} | |
void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex) | |
{ | |
_list.CopyTo(array, arrayIndex); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment