feat: Additional binary search extensions, AddSorted methods renamed to InsertSorted

This commit is contained in:
Chris Cameron
2019-09-23 11:43:43 -04:00
parent 602f170091
commit 0e16606d75
5 changed files with 237 additions and 37 deletions

View File

@@ -8,14 +8,14 @@ namespace ICD.Common.Utils.Tests.Extensions
public sealed class ListExtensionsTest public sealed class ListExtensionsTest
{ {
[Test] [Test]
public void AddSortedTest() public void InsertSortedTest()
{ {
List<int> testList = new List<int>(); List<int> testList = new List<int>();
Assert.AreEqual(0, testList.AddSorted(2)); Assert.AreEqual(0, testList.InsertSorted(2));
Assert.AreEqual(1, testList.AddSorted(3)); Assert.AreEqual(1, testList.InsertSorted(3));
Assert.AreEqual(0, testList.AddSorted(1)); Assert.AreEqual(0, testList.InsertSorted(1));
Assert.AreEqual(1, testList.AddSorted(2)); Assert.AreEqual(1, testList.InsertSorted(2));
Assert.AreEqual(4, testList.Count); Assert.AreEqual(4, testList.Count);
Assert.AreEqual(1, testList[0]); Assert.AreEqual(1, testList[0]);
@@ -25,15 +25,15 @@ namespace ICD.Common.Utils.Tests.Extensions
} }
[Test] [Test]
public void AddSortedComparerTest() public void InsertSortedComparerTest()
{ {
List<int> testList = new List<int>(); List<int> testList = new List<int>();
IComparer<int> comparer = new InverseComparer(); IComparer<int> comparer = new InverseComparer();
Assert.AreEqual(0, testList.AddSorted(2, comparer)); Assert.AreEqual(0, testList.InsertSorted(2, comparer));
Assert.AreEqual(0, testList.AddSorted(3, comparer)); Assert.AreEqual(0, testList.InsertSorted(3, comparer));
Assert.AreEqual(2, testList.AddSorted(1, comparer)); Assert.AreEqual(2, testList.InsertSorted(1, comparer));
Assert.AreEqual(1, testList.AddSorted(2, comparer)); Assert.AreEqual(1, testList.InsertSorted(2, comparer));
Assert.AreEqual(4, testList.Count); Assert.AreEqual(4, testList.Count);
Assert.AreEqual(3, testList[0]); Assert.AreEqual(3, testList[0]);

View File

@@ -106,7 +106,7 @@ namespace ICD.Common.Utils.Collections
if (m_Dictionary.ContainsKey(key)) if (m_Dictionary.ContainsKey(key))
throw new ArgumentOutOfRangeException("key", "An item with the same key has already been added."); throw new ArgumentOutOfRangeException("key", "An item with the same key has already been added.");
int index = m_OrderedKeys.AddSorted(key, m_Comparer); int index = m_OrderedKeys.InsertSorted(key, m_Comparer);
m_ValuesOrderedByKey.Insert(index, value); m_ValuesOrderedByKey.Insert(index, value);
m_Dictionary[key] = value; m_Dictionary[key] = value;

View File

@@ -10,14 +10,157 @@ namespace ICD.Common.Utils.Extensions
/// </summary> /// </summary>
public static class ListExtensions public static class ListExtensions
{ {
#region Add Sorted
/// <summary> /// <summary>
/// Adds the items into a sorted list. /// Attempts to add the item to the sorted list.
/// Returns false if the item already exists in the list.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="extends"></param>
/// <param name="item"></param>
/// <returns></returns>
[PublicAPI]
public static bool AddSorted<T>(this IList<T> extends, T item)
{
if (extends == null)
throw new ArgumentNullException("extends");
return extends.AddSorted(item, Comparer<T>.Default);
}
/// <summary>
/// Attempts to add the item to the sorted list.
/// Returns false if the item already exists in the list.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="TProp"></typeparam>
/// <param name="extends"></param>
/// <param name="item"></param>
/// <param name="predicate"></param>
[PublicAPI]
public static bool AddSorted<T, TProp>(this IList<T> extends, T item, Func<T, TProp> predicate)
{
if (extends == null)
throw new ArgumentNullException("extends");
if (predicate == null)
throw new ArgumentNullException("predicate");
PredicateComparer<T, TProp> comparer = new PredicateComparer<T, TProp>(predicate);
return extends.AddSorted(item, comparer);
}
/// <summary>
/// Attempts to add the item to the sorted list.
/// Returns false if the item already exists in the list.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="extends"></param>
/// <param name="item"></param>
/// <param name="comparer"></param>
/// <returns></returns>
[PublicAPI]
public static bool AddSorted<T>(this IList<T> extends, T item, IComparer<T> comparer)
{
if (extends == null)
throw new ArgumentNullException("extends");
if (comparer == null)
throw new ArgumentNullException("comparer");
int index = extends.BinarySearch(item, comparer);
if (index >= 0)
return false;
index = ~index;
extends.Insert(index, item);
return true;
}
#endregion
#region Remove Sorted
/// <summary>
/// Attempts to remove the item from the sorted list.
/// Returns false if the item does not exist in the list.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="extends"></param>
/// <param name="item"></param>
/// <returns></returns>
[PublicAPI]
public static bool RemoveSorted<T>(this IList<T> extends, T item)
{
if (extends == null)
throw new ArgumentNullException("extends");
return extends.RemoveSorted(item, Comparer<T>.Default);
}
/// <summary>
/// Attempts to remove the item from the sorted list.
/// Returns false if the item does not exist in the list.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="TProp"></typeparam>
/// <param name="extends"></param>
/// <param name="item"></param>
/// <param name="predicate"></param>
[PublicAPI]
public static bool RemoveSorted<T, TProp>(this IList<T> extends, T item, Func<T, TProp> predicate)
{
if (extends == null)
throw new ArgumentNullException("extends");
if (predicate == null)
throw new ArgumentNullException("predicate");
PredicateComparer<T, TProp> comparer = new PredicateComparer<T, TProp>(predicate);
return extends.RemoveSorted(item, comparer);
}
/// <summary>
/// Attempts to remove the item from the sorted list.
/// Returns false if the item does not exist in the list.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="extends"></param>
/// <param name="item"></param>
/// <param name="comparer"></param>
/// <returns></returns>
[PublicAPI]
public static bool RemoveSorted<T>(this IList<T> extends, T item, IComparer<T> comparer)
{
if (extends == null)
throw new ArgumentNullException("extends");
if (comparer == null)
throw new ArgumentNullException("comparer");
int index = extends.BinarySearch(item, comparer);
if (index < 0)
return false;
extends.RemoveAt(index);
return true;
}
#endregion
#region Insert Sorted
/// <summary>
/// Inserts the items into a sorted list.
/// </summary> /// </summary>
/// <typeparam name="T"></typeparam> /// <typeparam name="T"></typeparam>
/// <param name="extends"></param> /// <param name="extends"></param>
/// <param name="items"></param> /// <param name="items"></param>
[PublicAPI] [PublicAPI]
public static void AddSorted<T>(this IList<T> extends, IEnumerable<T> items) public static void InsertSorted<T>(this IList<T> extends, IEnumerable<T> items)
{ {
if (extends == null) if (extends == null)
throw new ArgumentNullException("extends"); throw new ArgumentNullException("extends");
@@ -25,18 +168,18 @@ namespace ICD.Common.Utils.Extensions
if (items == null) if (items == null)
throw new ArgumentNullException("items"); throw new ArgumentNullException("items");
extends.AddSorted(items, Comparer<T>.Default); extends.InsertSorted(items, Comparer<T>.Default);
} }
/// <summary> /// <summary>
/// Adds the items into a sorted list. /// Inserts the items into a sorted list.
/// </summary> /// </summary>
/// <typeparam name="T"></typeparam> /// <typeparam name="T"></typeparam>
/// <param name="extends"></param> /// <param name="extends"></param>
/// <param name="items"></param> /// <param name="items"></param>
/// <param name="comparer"></param> /// <param name="comparer"></param>
[PublicAPI] [PublicAPI]
public static void AddSorted<T>(this IList<T> extends, IEnumerable<T> items, IComparer<T> comparer) public static void InsertSorted<T>(this IList<T> extends, IEnumerable<T> items, IComparer<T> comparer)
{ {
if (extends == null) if (extends == null)
throw new ArgumentNullException("extends"); throw new ArgumentNullException("extends");
@@ -47,11 +190,11 @@ namespace ICD.Common.Utils.Extensions
if (comparer == null) if (comparer == null)
throw new ArgumentNullException("comparer"); throw new ArgumentNullException("comparer");
items.ForEach(i => extends.AddSorted(i, comparer)); items.ForEach(i => extends.InsertSorted(i, comparer));
} }
/// <summary> /// <summary>
/// Adds the items into a sorted list. /// Inserts the items into a sorted list.
/// </summary> /// </summary>
/// <typeparam name="T"></typeparam> /// <typeparam name="T"></typeparam>
/// <typeparam name="TProp"></typeparam> /// <typeparam name="TProp"></typeparam>
@@ -59,7 +202,7 @@ namespace ICD.Common.Utils.Extensions
/// <param name="items"></param> /// <param name="items"></param>
/// <param name="predicate"></param> /// <param name="predicate"></param>
[PublicAPI] [PublicAPI]
public static void AddSorted<T, TProp>(this IList<T> extends, IEnumerable<T> items, Func<T, TProp> predicate) public static void InsertSorted<T, TProp>(this IList<T> extends, IEnumerable<T> items, Func<T, TProp> predicate)
{ {
if (extends == null) if (extends == null)
throw new ArgumentNullException("extends"); throw new ArgumentNullException("extends");
@@ -71,33 +214,54 @@ namespace ICD.Common.Utils.Extensions
throw new ArgumentNullException("predicate"); throw new ArgumentNullException("predicate");
PredicateComparer<T, TProp> comparer = new PredicateComparer<T, TProp>(predicate); PredicateComparer<T, TProp> comparer = new PredicateComparer<T, TProp>(predicate);
extends.AddSorted(items, comparer); extends.InsertSorted(items, comparer);
} }
/// <summary> /// <summary>
/// Adds the item into a sorted list. /// Inserts the item into a sorted list.
/// </summary> /// </summary>
/// <typeparam name="T"></typeparam> /// <typeparam name="T"></typeparam>
/// <param name="extends"></param> /// <param name="extends"></param>
/// <param name="item"></param> /// <param name="item"></param>
[PublicAPI] [PublicAPI]
public static int AddSorted<T>(this IList<T> extends, T item) public static int InsertSorted<T>(this IList<T> extends, T item)
{ {
if (extends == null) if (extends == null)
throw new ArgumentNullException("extends"); throw new ArgumentNullException("extends");
return extends.AddSorted(item, Comparer<T>.Default); return extends.InsertSorted(item, Comparer<T>.Default);
} }
/// <summary> /// <summary>
/// Adds the item into a sorted list. /// Inserts the item into a sorted list.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="TProp"></typeparam>
/// <param name="extends"></param>
/// <param name="item"></param>
/// <param name="predicate"></param>
[PublicAPI]
public static int InsertSorted<T, TProp>(this IList<T> extends, T item, Func<T, TProp> predicate)
{
if (extends == null)
throw new ArgumentNullException("extends");
if (predicate == null)
throw new ArgumentNullException("predicate");
PredicateComparer<T, TProp> comparer = new PredicateComparer<T, TProp>(predicate);
return extends.InsertSorted(item, comparer);
}
/// <summary>
/// Inserts the item into a sorted list.
/// </summary> /// </summary>
/// <typeparam name="T"></typeparam> /// <typeparam name="T"></typeparam>
/// <param name="extends"></param> /// <param name="extends"></param>
/// <param name="item"></param> /// <param name="item"></param>
/// <param name="comparer"></param> /// <param name="comparer"></param>
[PublicAPI] [PublicAPI]
public static int AddSorted<T>(this IList<T> extends, T item, IComparer<T> comparer) public static int InsertSorted<T>(this IList<T> extends, T item, IComparer<T> comparer)
{ {
if (extends == null) if (extends == null)
throw new ArgumentNullException("extends"); throw new ArgumentNullException("extends");
@@ -114,27 +278,50 @@ namespace ICD.Common.Utils.Extensions
return index; return index;
} }
#endregion
#region Contains Sorted
/// <summary> /// <summary>
/// Adds the item into a sorted list. /// Returns true if the sorted list contains the given item.
/// </summary> /// </summary>
/// <typeparam name="T"></typeparam> /// <typeparam name="T"></typeparam>
/// <typeparam name="TProp"></typeparam>
/// <param name="extends"></param> /// <param name="extends"></param>
/// <param name="item"></param> /// <param name="item"></param>
/// <param name="predicate"></param> /// <returns></returns>
[PublicAPI] [PublicAPI]
public static int AddSorted<T, TProp>(this IList<T> extends, T item, Func<T, TProp> predicate) public static bool ContainsSorted<T>(this IList<T> extends, T item)
{ {
if (extends == null) if (extends == null)
throw new ArgumentNullException("extends"); throw new ArgumentNullException("extends");
if (predicate == null) return extends.ContainsSorted(item, Comparer<T>.Default);
throw new ArgumentNullException("predicate");
PredicateComparer<T, TProp> comparer = new PredicateComparer<T, TProp>(predicate);
return extends.AddSorted(item, comparer);
} }
/// <summary>
/// Returns true if the sorted list contains the given item.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="extends"></param>
/// <param name="item"></param>
/// <param name="comparer"></param>
/// <returns></returns>
[PublicAPI]
public static bool ContainsSorted<T>(this IList<T> extends, T item, IComparer<T> comparer)
{
if (extends == null)
throw new ArgumentNullException("extends");
if (comparer == null)
throw new ArgumentNullException("comparer");
return extends.BinarySearch(item, comparer) >= 0;
}
#endregion
#region Binary Search
/// <summary> /// <summary>
/// Returns the index of the item in the list. /// Returns the index of the item in the list.
/// </summary> /// </summary>
@@ -152,6 +339,17 @@ namespace ICD.Common.Utils.Extensions
if (comparer == null) if (comparer == null)
throw new ArgumentNullException("comparer"); throw new ArgumentNullException("comparer");
// Array
T[] array = extends as T[];
if (array != null)
return Array.BinarySearch(array, 0, array.Length, item, comparer);
// List
List<T> list = extends as List<T>;
if (list != null)
return list.BinarySearch(item, comparer);
// IList
int lo = 0; int lo = 0;
int hi = extends.Count - 1; int hi = extends.Count - 1;
@@ -171,5 +369,7 @@ namespace ICD.Common.Utils.Extensions
return ~lo; return ~lo;
} }
#endregion
} }
} }

View File

@@ -39,7 +39,7 @@ namespace ICD.Common.Utils.Services.Scheduler
try try
{ {
Subscribe(action); Subscribe(action);
m_Actions.AddSorted(action, a => a.NextRunTime); m_Actions.InsertSorted(action, a => a.NextRunTime);
} }
finally finally
{ {
@@ -195,7 +195,7 @@ namespace ICD.Common.Utils.Services.Scheduler
try try
{ {
m_Actions.Remove(action); m_Actions.Remove(action);
m_Actions.AddSorted(action, a => a.NextRunTime); m_Actions.InsertSorted(action, a => a.NextRunTime);
} }
finally finally
{ {

View File

@@ -178,7 +178,7 @@ namespace ICD.Common.Utils.Timers
long duration = stopwatch.ElapsedTicks; long duration = stopwatch.ElapsedTicks;
stopwatch.Stop(); stopwatch.Stop();
orderedMs.AddSorted(duration); orderedMs.InsertSorted(duration);
totalTicks += duration; totalTicks += duration;
} }