Skip to content

Instantly share code, notes, and snippets.

@SolidAlloy
Last active June 18, 2020 08:01
Show Gist options
  • Save SolidAlloy/9d77972f0bb1f0be91f63af66417c815 to your computer and use it in GitHub Desktop.
Save SolidAlloy/9d77972f0bb1f0be91f63af66417c815 to your computer and use it in GitHub Desktop.
A dictionary implementation that generates keys automatically and returns them in the Add() method.
// A dictionary implementation that generates keys automatically and returns them in the Add() method.
// This is basically a nicely presented copy of the code snippet from this post
// https://stackoverflow.com/a/39104018/9833103
namespace CustomDataStructures
{
using System;
using System.Collections;
using System.Collections.Generic;
internal class AutoKeyDictionary<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>>
{
private readonly Dictionary<TKey, TValue> _inner;
private readonly Func<TKey, TKey> _incrementor;
private readonly Stack<TKey> _freeKeys;
private readonly TKey _keySeed;
private TKey _currentKey;
public AutoKeyDictionary(TKey keySeed, Func<TKey, TKey> incrementor)
{
if (keySeed == null)
throw new ArgumentNullException(nameof(keySeed));
if (incrementor == null)
throw new ArgumentNullException(nameof(incrementor));
_inner = new Dictionary<TKey, TValue>();
_freeKeys = new Stack<TKey>();
_currentKey = keySeed;
}
public int Count => _inner.Count;
public Dictionary<TKey, TValue>.KeyCollection Keys => _inner.Keys;
public Dictionary<TKey, TValue>.ValueCollection Values => _inner.Values;
public TValue this[TKey key] { get => _inner[key]; set => _inner[key] = value; }
public TKey Add(TValue value) // returns the used key
{
TKey usedKey;
if (_freeKeys.Count > 0)
{
usedKey = _freeKeys.Pop();
_inner.Add(usedKey, value);
}
else
{
usedKey = _currentKey;
_inner.Add(usedKey, value);
_currentKey = _incrementor(_currentKey);
}
return usedKey;
}
public void Clear()
{
_inner.Clear();
_freeKeys.Clear();
_currentKey = _keySeed;
}
public bool Remove(TKey key)
{
if (!_inner.Remove(key))
return false;
if (_inner.Count > 0)
{
_freeKeys.Push(key);
}
else
{
_freeKeys.Clear();
_currentKey = _keySeed;
}
return true;
}
public bool TryGetValue(TKey key, out TValue value)
{
return _inner.TryGetValue(key, out value);
}
public bool ContainsKey(TKey key)
{
return _inner.ContainsKey(key);
}
public bool ContainsValue(TValue value)
{
return _inner.ContainsValue(value);
}
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
{
return _inner.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable)_inner).GetEnumerator();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment