From b2b6862943fcc6116e201d6d2217be91477d19eb Mon Sep 17 00:00:00 2001 From: MarcUs7i <96580944+MarcUs7i@users.noreply.github.com> Date: Mon, 20 Jan 2025 21:03:31 +0100 Subject: [PATCH] Implemented MyDictionary.cs --- BuildingDirectory/MyDictionary.cs | 184 +++++++++++++++++++++++++++--- 1 file changed, 166 insertions(+), 18 deletions(-) diff --git a/BuildingDirectory/MyDictionary.cs b/BuildingDirectory/MyDictionary.cs index 25a5950..88d4249 100644 --- a/BuildingDirectory/MyDictionary.cs +++ b/BuildingDirectory/MyDictionary.cs @@ -1,4 +1,5 @@ using System.Diagnostics.CodeAnalysis; +using BuildingDirectory.Model; namespace BuildingDirectory; @@ -11,17 +12,14 @@ public sealed class MyDictionary where TKey : notnull { private const int InitialBuckets = 4; private const int MaxDepth = 2; - // TODO - //private List[] _buckets; - //private int _currentMaxDepth; + private List[] _buckets; + private int _currentMaxDepth; /// /// Gets the count of items stored in this dictionary /// public int Count { get; private set; } - - // TODO - private int NoOfBuckets => -1; + private int NoOfBuckets => _buckets.Length; /// /// Creates a new instance of the dictionary with default capacity @@ -32,7 +30,9 @@ public sealed class MyDictionary where TKey : notnull private MyDictionary(int capacity) { - // TODO + _buckets = CreateBuckets(capacity); + // idk, guess I won't use it + _currentMaxDepth = capacity; } /// @@ -40,8 +40,14 @@ public sealed class MyDictionary where TKey : notnull /// Returns the default value for if not found. /// /// Key of the required value - // TODO - public TValue? this[TKey key] => default; + public TValue? this[TKey key] + { + get + { + TryGetValue(key, out TValue? value); + return value ?? default; + } + } /// /// Returns a list of all managed keys. @@ -49,8 +55,13 @@ public sealed class MyDictionary where TKey : notnull /// A list of all keys public List GetKeys() { - // TODO - return new(); + var keysAndValues = GetKeysAndValues(); + List keys = []; + foreach (var keyValue in keysAndValues) + { + keys.Add(keyValue.Key); + } + return keys; } /// @@ -60,8 +71,13 @@ public sealed class MyDictionary where TKey : notnull /// A list of all values public List GetValues() { - // TODO - return new(); + var keysAndValues = GetKeysAndValues(); + List values = []; + foreach (var keyValue in keysAndValues) + { + values.Add(keyValue.Value); + } + return values; } /// @@ -72,7 +88,19 @@ public sealed class MyDictionary where TKey : notnull /// Value to store 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++; } /// @@ -83,7 +111,16 @@ public sealed class MyDictionary where TKey : notnull /// True if the key & value could be removed; false otherwise 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; } @@ -96,9 +133,15 @@ public sealed class MyDictionary where TKey : notnull /// True if key was found; false otherwise public bool TryGetValue(TKey key, out TValue? value) { - // TODO value = default; - return false; + var found = TryGetValue(key, out KeyValue? keyValue); + if (keyValue == null) + { + return false; + } + + value = keyValue.Value; + return found; } /// @@ -108,7 +151,112 @@ public sealed class MyDictionary where TKey : notnull /// True if key is found; false otherwise 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; } + + 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 GetKeysAndValues() + { + List 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[] CreateBuckets(int amount) + { + var buckets = new List[amount]; + for (var i = 0; i < amount; i++) + { + buckets[i] = new List(); + } + 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(); + } + } } \ No newline at end of file