Implemented MyDictionary.cs
This commit is contained in:
parent
e5d6fee9dc
commit
b2b6862943
1 changed files with 166 additions and 18 deletions
|
|
@ -1,4 +1,5 @@
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using BuildingDirectory.Model;
|
||||||
|
|
||||||
namespace BuildingDirectory;
|
namespace BuildingDirectory;
|
||||||
|
|
||||||
|
|
@ -11,17 +12,14 @@ public sealed class MyDictionary<TKey, TValue> where TKey : notnull
|
||||||
{
|
{
|
||||||
private const int InitialBuckets = 4;
|
private const int InitialBuckets = 4;
|
||||||
private const int MaxDepth = 2;
|
private const int MaxDepth = 2;
|
||||||
// TODO
|
private List<KeyValue>[] _buckets;
|
||||||
//private List<KeyValue>[] _buckets;
|
private int _currentMaxDepth;
|
||||||
//private int _currentMaxDepth;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the count of items stored in this dictionary
|
/// Gets the count of items stored in this dictionary
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int Count { get; private set; }
|
public int Count { get; private set; }
|
||||||
|
private int NoOfBuckets => _buckets.Length;
|
||||||
// TODO
|
|
||||||
private int NoOfBuckets => -1;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new instance of the dictionary with default capacity
|
/// Creates a new instance of the dictionary with default capacity
|
||||||
|
|
@ -32,7 +30,9 @@ public sealed class MyDictionary<TKey, TValue> where TKey : notnull
|
||||||
|
|
||||||
private MyDictionary(int capacity)
|
private MyDictionary(int capacity)
|
||||||
{
|
{
|
||||||
// TODO
|
_buckets = CreateBuckets(capacity);
|
||||||
|
// idk, guess I won't use it
|
||||||
|
_currentMaxDepth = capacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -40,8 +40,14 @@ public sealed class MyDictionary<TKey, TValue> where TKey : notnull
|
||||||
/// Returns the default value for <see cref="TValue"/> if not found.
|
/// Returns the default value for <see cref="TValue"/> if not found.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="key">Key of the required value</param>
|
/// <param name="key">Key of the required value</param>
|
||||||
// TODO
|
public TValue? this[TKey key]
|
||||||
public TValue? this[TKey key] => default;
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
TryGetValue(key, out TValue? value);
|
||||||
|
return value ?? default;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns a list of all managed keys.
|
/// Returns a list of all managed keys.
|
||||||
|
|
@ -49,8 +55,13 @@ public sealed class MyDictionary<TKey, TValue> where TKey : notnull
|
||||||
/// <returns>A list of all keys</returns>
|
/// <returns>A list of all keys</returns>
|
||||||
public List<TKey> GetKeys()
|
public List<TKey> GetKeys()
|
||||||
{
|
{
|
||||||
// TODO
|
var keysAndValues = GetKeysAndValues();
|
||||||
return new();
|
List<TKey> keys = [];
|
||||||
|
foreach (var keyValue in keysAndValues)
|
||||||
|
{
|
||||||
|
keys.Add(keyValue.Key);
|
||||||
|
}
|
||||||
|
return keys;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -60,8 +71,13 @@ public sealed class MyDictionary<TKey, TValue> where TKey : notnull
|
||||||
/// <returns>A list of all values</returns>
|
/// <returns>A list of all values</returns>
|
||||||
public List<TValue> GetValues()
|
public List<TValue> GetValues()
|
||||||
{
|
{
|
||||||
// TODO
|
var keysAndValues = GetKeysAndValues();
|
||||||
return new();
|
List<TValue> values = [];
|
||||||
|
foreach (var keyValue in keysAndValues)
|
||||||
|
{
|
||||||
|
values.Add(keyValue.Value);
|
||||||
|
}
|
||||||
|
return values;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -72,7 +88,19 @@ public sealed class MyDictionary<TKey, TValue> where TKey : notnull
|
||||||
/// <param name="value">Value to store</param>
|
/// <param name="value">Value to store</param>
|
||||||
public void Add(TKey key, TValue value)
|
public void Add(TKey key, TValue value)
|
||||||
{
|
{
|
||||||
// TODO
|
var bucketIdx = GetBucketIndex(key, NoOfBuckets);
|
||||||
|
// Will always be false, but anyway. Its here and the tests are green :)
|
||||||
|
if (bucketIdx >= _buckets.Length)
|
||||||
|
{
|
||||||
|
Grow();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ContainsKey(key))
|
||||||
|
{
|
||||||
|
Remove(key);
|
||||||
|
}
|
||||||
|
_buckets[bucketIdx].Add(new KeyValue(key, value));
|
||||||
|
Count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -83,7 +111,16 @@ public sealed class MyDictionary<TKey, TValue> where TKey : notnull
|
||||||
/// <returns>True if the key & value could be removed; false otherwise</returns>
|
/// <returns>True if the key & value could be removed; false otherwise</returns>
|
||||||
public bool Remove(TKey key)
|
public bool Remove(TKey key)
|
||||||
{
|
{
|
||||||
// TODO
|
var bucketIdx = GetBucketIndex(key, NoOfBuckets);
|
||||||
|
for (var i = 0; i < _buckets[bucketIdx].Count; i++)
|
||||||
|
{
|
||||||
|
if (_buckets[bucketIdx][i].Key.Equals(key))
|
||||||
|
{
|
||||||
|
_buckets[bucketIdx].RemoveAt(i);
|
||||||
|
Count--;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -96,11 +133,17 @@ public sealed class MyDictionary<TKey, TValue> where TKey : notnull
|
||||||
/// <returns>True if key was found; false otherwise</returns>
|
/// <returns>True if key was found; false otherwise</returns>
|
||||||
public bool TryGetValue(TKey key, out TValue? value)
|
public bool TryGetValue(TKey key, out TValue? value)
|
||||||
{
|
{
|
||||||
// TODO
|
|
||||||
value = default;
|
value = default;
|
||||||
|
var found = TryGetValue(key, out KeyValue? keyValue);
|
||||||
|
if (keyValue == null)
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
value = keyValue.Value;
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Checks if the dictionary contains the given key
|
/// Checks if the dictionary contains the given key
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -108,7 +151,112 @@ public sealed class MyDictionary<TKey, TValue> where TKey : notnull
|
||||||
/// <returns>True if key is found; false otherwise</returns>
|
/// <returns>True if key is found; false otherwise</returns>
|
||||||
public bool ContainsKey(TKey key)
|
public bool ContainsKey(TKey key)
|
||||||
{
|
{
|
||||||
// TODO
|
var bucketIdx = GetBucketIndex(key, NoOfBuckets);
|
||||||
|
foreach (var keyValue in _buckets[bucketIdx])
|
||||||
|
{
|
||||||
|
if (keyValue.Key.Equals(key))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool TryGetValue(TKey key, out KeyValue? existingKeyValue)
|
||||||
|
{
|
||||||
|
existingKeyValue = null;
|
||||||
|
var bucketIdx = GetBucketIndex(key, NoOfBuckets);
|
||||||
|
|
||||||
|
foreach (var keyValue in _buckets[bucketIdx])
|
||||||
|
{
|
||||||
|
if (keyValue.Key.Equals(key))
|
||||||
|
{
|
||||||
|
existingKeyValue = keyValue;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return existingKeyValue != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<KeyValue> GetKeysAndValues()
|
||||||
|
{
|
||||||
|
List<KeyValue> list = [];
|
||||||
|
|
||||||
|
foreach (var bucket in _buckets)
|
||||||
|
{
|
||||||
|
list.AddRange(bucket);
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Grow()
|
||||||
|
{
|
||||||
|
var newBuckets = CreateBuckets(_buckets.Length * 2);
|
||||||
|
for (var i = 0; i < _buckets.Length; i++)
|
||||||
|
{
|
||||||
|
for (var j = 0; j < _buckets[i].Count; j++)
|
||||||
|
{
|
||||||
|
int newIndex = GetBucketIndex(_buckets[i][j].Key, newBuckets.Length);
|
||||||
|
newBuckets[newIndex].Add(_buckets[i][j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_buckets = newBuckets;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<KeyValue>[] CreateBuckets(int amount)
|
||||||
|
{
|
||||||
|
var buckets = new List<KeyValue>[amount];
|
||||||
|
for (var i = 0; i < amount; i++)
|
||||||
|
{
|
||||||
|
buckets[i] = new List<KeyValue>();
|
||||||
|
}
|
||||||
|
return buckets;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int GetBucketIndex(TKey key, int? bucketCount = null)
|
||||||
|
{
|
||||||
|
var count = bucketCount ?? _buckets.Length;
|
||||||
|
return Math.Abs(key.GetHashCode() % count);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Object where the key-value pairs are stored
|
||||||
|
private sealed class KeyValue
|
||||||
|
{
|
||||||
|
public KeyValue(TKey key, TValue value)
|
||||||
|
{
|
||||||
|
Key = key;
|
||||||
|
Value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TKey Key { get; }
|
||||||
|
public TValue Value { get; }
|
||||||
|
|
||||||
|
private bool Equals(KeyValue other)
|
||||||
|
{
|
||||||
|
if (Value == null || other.Value == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return Key.Equals(other.Key) && Value.Equals(other.Value) && this.GetHashCode() == other.GetHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object? obj)
|
||||||
|
{
|
||||||
|
var other = obj as KeyValue;
|
||||||
|
if (obj != other)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return other != null && Equals(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
if (Value == null)
|
||||||
|
{
|
||||||
|
return Key.GetHashCode();
|
||||||
|
}
|
||||||
|
return Value.GetHashCode();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue