From ac4c0eccc9619efc87665b8ddd82fc69e1da6c2f Mon Sep 17 00:00:00 2001 From: Jack Kanarish Date: Fri, 17 Jan 2020 17:01:31 -0500 Subject: [PATCH] feat: add ability to select when de-duplication should queue at the end of the queue, or at the first occurance # Conflicts: # ICD.Common.Utils/Collections/PriorityQueue.cs --- ICD.Common.Utils/Collections/PriorityQueue.cs | 39 +++++++++++++++++-- .../Extensions/DictionaryExtensions.cs | 35 +++++++++++++++++ 2 files changed, 71 insertions(+), 3 deletions(-) diff --git a/ICD.Common.Utils/Collections/PriorityQueue.cs b/ICD.Common.Utils/Collections/PriorityQueue.cs index 6d18399..7adc438 100644 --- a/ICD.Common.Utils/Collections/PriorityQueue.cs +++ b/ICD.Common.Utils/Collections/PriorityQueue.cs @@ -84,6 +84,20 @@ namespace ICD.Common.Utils.Collections m_Count++; } + /// + /// Adds the item to the queue with the given priority at the given index. + /// + /// + /// + /// + [PublicAPI] + public void Enqueue([CanBeNull] T item, int priority, int position) + { + m_PriorityToQueue.GetOrAddNew(priority, ()=> new List()) + .Insert(position, item); + m_Count++; + } + /// /// Enqueues the item at the beginning of the queue. /// @@ -117,7 +131,7 @@ namespace ICD.Common.Utils.Collections if (remove == null) throw new ArgumentNullException("remove"); - EnqueueRemove(item, remove, int.MaxValue); + EnqueueRemove(item, remove, int.MaxValue, false); } /// @@ -128,12 +142,16 @@ namespace ICD.Common.Utils.Collections /// /// /// + /// [PublicAPI] - public void EnqueueRemove(T item, Func remove, int priority) + public void EnqueueRemove([CanBeNull] T item, [NotNull] Func remove, int priority, bool deDuplicateToEndOfQueue) { if (remove == null) throw new ArgumentNullException("remove"); + int lowestMatchingPriority = int.MaxValue; + int? firstMatchingIndex = null; + foreach (KeyValuePair> kvp in m_PriorityToQueue.ToArray()) { int[] removeIndices = @@ -142,6 +160,12 @@ namespace ICD.Common.Utils.Collections .Reverse() .ToArray(); + if (removeIndices.Any() && kvp.Key < lowestMatchingPriority ) + { + lowestMatchingPriority = kvp.Key; + firstMatchingIndex = removeIndices.Last(); + } + foreach (int removeIndex in removeIndices) { kvp.Value.RemoveAt(removeIndex); @@ -152,7 +176,16 @@ namespace ICD.Common.Utils.Collections m_PriorityToQueue.Remove(kvp.Key); } - Enqueue(item, priority); + + if(deDuplicateToEndOfQueue) + Enqueue(item, priority); + else + { + if(firstMatchingIndex == null) + Enqueue(item, lowestMatchingPriority); + else + Enqueue(item, lowestMatchingPriority, firstMatchingIndex.Value); + } } /// diff --git a/ICD.Common.Utils/Extensions/DictionaryExtensions.cs b/ICD.Common.Utils/Extensions/DictionaryExtensions.cs index cc3f582..a484a46 100644 --- a/ICD.Common.Utils/Extensions/DictionaryExtensions.cs +++ b/ICD.Common.Utils/Extensions/DictionaryExtensions.cs @@ -130,6 +130,41 @@ namespace ICD.Common.Utils.Extensions return value; } + /// + /// If the key is present in the dictionary return the value, otherwise add a new value to the dictionary and return it. + /// + /// + /// + /// + /// + /// + /// + [PublicAPI] + public static TValue GetOrAddNew([NotNull] this IDictionary extends, + [NotNull] TKey key, + [NotNull] Func valueFunc) + { + if (extends == null) + throw new ArgumentNullException("extends"); + + // ReSharper disable CompareNonConstrainedGenericWithNull + if (key == null) + // ReSharper restore CompareNonConstrainedGenericWithNull + throw new ArgumentNullException("key"); + + if (valueFunc == null) + throw new ArgumentNullException("valueFunc"); + + TValue value; + if (!extends.TryGetValue(key, out value)) + { + value = valueFunc(); + extends.Add(key, value); + } + + return value; + } + /// /// Gets a key for the given value. ///