From ac4c0eccc9619efc87665b8ddd82fc69e1da6c2f Mon Sep 17 00:00:00 2001 From: Jack Kanarish Date: Fri, 17 Jan 2020 17:01:31 -0500 Subject: [PATCH 1/3] 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. /// From b74d2c9d6073649eb4a74887fa059774e05436e6 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Thu, 23 Jan 2020 12:44:08 -0500 Subject: [PATCH 2/3] fix: Adding PriorityQueue EnqueueRemove overload for backwards compat --- ICD.Common.Utils/Collections/PriorityQueue.cs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/ICD.Common.Utils/Collections/PriorityQueue.cs b/ICD.Common.Utils/Collections/PriorityQueue.cs index 7adc438..f269c2d 100644 --- a/ICD.Common.Utils/Collections/PriorityQueue.cs +++ b/ICD.Common.Utils/Collections/PriorityQueue.cs @@ -131,7 +131,24 @@ namespace ICD.Common.Utils.Collections if (remove == null) throw new ArgumentNullException("remove"); - EnqueueRemove(item, remove, int.MaxValue, false); + EnqueueRemove(item, remove, int.MaxValue); + } + + /// + /// Removes any items in the queue matching the predicate. + /// Appends the given item at the end of the given priority level. + /// This is useful for reducing duplication, or replacing items with something more pertinent. + /// + /// + /// + /// + [PublicAPI] + public void EnqueueRemove([CanBeNull] T item, [NotNull] Func remove, int priority) + { + if (remove == null) + throw new ArgumentNullException("remove"); + + EnqueueRemove(item, remove, priority, false); } /// From d02594694832da02833ea533c8f362338cd94180 Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Thu, 23 Jan 2020 12:46:06 -0500 Subject: [PATCH 3/3] chore: Updating changelog, incrementing minor version --- CHANGELOG.md | 4 ++++ ICD.Common.Utils/Properties/AssemblyInfo.cs | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ef41f0..a14fd3a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] +## [8.8.0] - 2020-01-23 +### Added + - Added an overload to PriorityQueue for determing the de-duplication behaviour + ## [8.7.2] - 2019-10-29 ### Changed - Fixed a bug with PriorityQueue de-duplication where a new command would be inserted in the wrong position diff --git a/ICD.Common.Utils/Properties/AssemblyInfo.cs b/ICD.Common.Utils/Properties/AssemblyInfo.cs index 5a7bb24..db83791 100644 --- a/ICD.Common.Utils/Properties/AssemblyInfo.cs +++ b/ICD.Common.Utils/Properties/AssemblyInfo.cs @@ -4,4 +4,4 @@ using System.Reflection; [assembly: AssemblyCompany("ICD Systems")] [assembly: AssemblyProduct("ICD.Common.Utils")] [assembly: AssemblyCopyright("Copyright © ICD Systems 2019")] -[assembly: AssemblyVersion("8.7.2.0")] +[assembly: AssemblyVersion("8.8.0.0")]