Skip to content

Instantly share code, notes, and snippets.

@YairHalberstadt
Created August 26, 2020 05:56
Show Gist options
  • Save YairHalberstadt/1d4d9cf3a831e9227980fefed70e73e6 to your computer and use it in GitHub Desktop.
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
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