Entension methods for finding indices in a sequence, and finding the closest item in a sequence

This commit is contained in:
Chris Cameron
2017-12-08 14:51:51 -05:00
parent 6fa4945b95
commit 1039caa016
2 changed files with 379 additions and 329 deletions

View File

@@ -37,7 +37,7 @@ namespace ICD.Common.Utils.Tests.Extensions
Assert.AreEqual(0, result); Assert.AreEqual(0, result);
Assert.AreEqual(false, exists); Assert.AreEqual(false, exists);
sequence = new[] { expected }; sequence = new[] {expected};
exists = sequence.TryFirst(out result); exists = sequence.TryFirst(out result);
Assert.AreEqual(expected, result); Assert.AreEqual(expected, result);
@@ -55,7 +55,7 @@ namespace ICD.Common.Utils.Tests.Extensions
Assert.AreEqual(0, result); Assert.AreEqual(0, result);
Assert.AreEqual(false, exists); Assert.AreEqual(false, exists);
sequence = new[] { expected }; sequence = new[] {expected};
exists = sequence.TryFirst(i => i == expected, out result); exists = sequence.TryFirst(i => i == expected, out result);
Assert.AreEqual(expected, result); Assert.AreEqual(expected, result);
@@ -73,7 +73,7 @@ namespace ICD.Common.Utils.Tests.Extensions
Assert.AreEqual(0, result); Assert.AreEqual(0, result);
Assert.AreEqual(false, exists); Assert.AreEqual(false, exists);
sequence = new[] { expected }; sequence = new[] {expected};
exists = sequence.TryElementAt(0, out result); exists = sequence.TryElementAt(0, out result);
Assert.AreEqual(expected, result); Assert.AreEqual(expected, result);
@@ -83,8 +83,8 @@ namespace ICD.Common.Utils.Tests.Extensions
[Test] [Test]
public void SequenceEqualTest() public void SequenceEqualTest()
{ {
int[] a = new[] { 1, 2, 3, 4}; int[] a = new[] {1, 2, 3, 4};
int[] b = new[] { 1, 4, 9, 16}; int[] b = new[] {1, 4, 9, 16};
Assert.IsFalse(a.SequenceEqual(b, (x, y) => x == y)); Assert.IsFalse(a.SequenceEqual(b, (x, y) => x == y));
Assert.IsTrue(a.SequenceEqual(b, (x, y) => x * x == y)); Assert.IsTrue(a.SequenceEqual(b, (x, y) => x * x == y));
@@ -93,10 +93,10 @@ namespace ICD.Common.Utils.Tests.Extensions
[Test] [Test]
public void ScrambledEqualsTest() public void ScrambledEqualsTest()
{ {
IEnumerable<int> a = new[] { 1, 2, 3, 4 }; IEnumerable<int> a = new[] {1, 2, 3, 4};
IEnumerable<int> b = new[] { 3, 1, 2, 4 }; IEnumerable<int> b = new[] {3, 1, 2, 4};
IEnumerable<int> c = new[] { 1, 2, 3, 4, 4 }; IEnumerable<int> c = new[] {1, 2, 3, 4, 4};
IEnumerable<int> d = new[] { 1, 2, 3, 4, 5 }; IEnumerable<int> d = new[] {1, 2, 3, 4, 5};
Assert.IsTrue(a.ScrambledEquals(b)); Assert.IsTrue(a.ScrambledEquals(b));
Assert.IsFalse(a.ScrambledEquals(c)); Assert.IsFalse(a.ScrambledEquals(c));
@@ -106,10 +106,10 @@ namespace ICD.Common.Utils.Tests.Extensions
[Test] [Test]
public void ScrambledEqualsComparerTest() public void ScrambledEqualsComparerTest()
{ {
IEnumerable<int> a = new[] { 1, 2, 3, 4 }; IEnumerable<int> a = new[] {1, 2, 3, 4};
IEnumerable<int> b = new[] { 3, 1, 2, 4 }; IEnumerable<int> b = new[] {3, 1, 2, 4};
IEnumerable<int> c = new[] { 1, 2, 3, 4, 4 }; IEnumerable<int> c = new[] {1, 2, 3, 4, 4};
IEnumerable<int> d = new[] { 1, 2, 3, 4, 5 }; IEnumerable<int> d = new[] {1, 2, 3, 4, 5};
Assert.IsTrue(a.ScrambledEquals(b, EqualityComparer<int>.Default)); Assert.IsTrue(a.ScrambledEquals(b, EqualityComparer<int>.Default));
Assert.IsFalse(a.ScrambledEquals(c, EqualityComparer<int>.Default)); Assert.IsFalse(a.ScrambledEquals(c, EqualityComparer<int>.Default));
@@ -119,14 +119,26 @@ namespace ICD.Common.Utils.Tests.Extensions
[Test] [Test]
public void FindIndexPredicateTest() public void FindIndexPredicateTest()
{ {
IEnumerable<int> a = new[] { 1, 2, 3, 4 }; IEnumerable<int> a = new[] {1, 2, 3, 4};
Assert.AreEqual(2, a.FindIndex(i => i == 3)); Assert.AreEqual(2, a.FindIndex(i => i == 3));
} }
[Test]
public void FindIndicesPredicateTest()
{
IEnumerable<int> a = new[] {1, 2, 3, 4};
int[] indices = a.FindIndices(i => i % 2 == 0).ToArray();
Assert.AreEqual(2, indices.Length);
Assert.AreEqual(1, indices[0]);
Assert.AreEqual(3, indices[1]);
}
[Test] [Test]
public void SelectMultiTest() public void SelectMultiTest()
{ {
int[] values = { 1, 2, 3 }; int[] values = {1, 2, 3};
int[] result = values.SelectMulti(i => 1, i => 2).ToArray(); int[] result = values.SelectMulti(i => 1, i => 2).ToArray();
Assert.AreEqual(6, result.Length); Assert.AreEqual(6, result.Length);
@@ -141,10 +153,14 @@ namespace ICD.Common.Utils.Tests.Extensions
[Test] [Test]
public void ExecuteTest() public void ExecuteTest()
{ {
int[] values = { 1, 2, 3 }; int[] values = {1, 2, 3};
int sum = 0; int sum = 0;
IEnumerable<int> sequence = values.Select(v => { sum += v; return v; }); IEnumerable<int> sequence = values.Select(v =>
{
sum += v;
return v;
});
Assert.AreEqual(0, sum); Assert.AreEqual(0, sum);
sequence.Execute(); sequence.Execute();
@@ -154,7 +170,7 @@ namespace ICD.Common.Utils.Tests.Extensions
[Test] [Test]
public void ForEachTest() public void ForEachTest()
{ {
int[] values = { 1, 2, 3 }; int[] values = {1, 2, 3};
int sum = 0; int sum = 0;
values.ForEach(v => sum += v); values.ForEach(v => sum += v);
@@ -165,7 +181,7 @@ namespace ICD.Common.Utils.Tests.Extensions
[Test] [Test]
public void ForEachIndexTest() public void ForEachIndexTest()
{ {
int[] values = { 1, 2, 3 }; int[] values = {1, 2, 3};
int sum = 0; int sum = 0;
values.ForEach((v, i) => sum += i); values.ForEach((v, i) => sum += i);
@@ -184,7 +200,7 @@ namespace ICD.Common.Utils.Tests.Extensions
[Test] [Test]
public void PrependManyTest() public void PrependManyTest()
{ {
int[] values = (new[] { 4, 5, 6 }).PrependMany(1, 2, 3).ToArray(); int[] values = (new[] {4, 5, 6}).PrependMany(1, 2, 3).ToArray();
Assert.AreEqual(6, values.Length); Assert.AreEqual(6, values.Length);
Assert.AreEqual(1, values[0]); Assert.AreEqual(1, values[0]);
@@ -206,7 +222,7 @@ namespace ICD.Common.Utils.Tests.Extensions
[Test] [Test]
public void AppendManyTest() public void AppendManyTest()
{ {
int[] values = (new[] { 1, 2, 3 }).AppendMany(4, 5, 6).ToArray(); int[] values = (new[] {1, 2, 3}).AppendMany(4, 5, 6).ToArray();
Assert.AreEqual(6, values.Length); Assert.AreEqual(6, values.Length);
Assert.AreEqual(1, values[0]); Assert.AreEqual(1, values[0]);
@@ -220,7 +236,7 @@ namespace ICD.Common.Utils.Tests.Extensions
[Test] [Test]
public void OrderTest() public void OrderTest()
{ {
int[] values = (new[] { 2, 3, 1 }).Order().ToArray(); int[] values = (new[] {2, 3, 1}).Order().ToArray();
Assert.AreEqual(3, values.Length); Assert.AreEqual(3, values.Length);
Assert.AreEqual(1, values[0]); Assert.AreEqual(1, values[0]);
@@ -231,7 +247,7 @@ namespace ICD.Common.Utils.Tests.Extensions
[Test] [Test]
public void ExceptTest() public void ExceptTest()
{ {
int[] values = (new[] { 1, 2, 3 }).Except(2).ToArray(); int[] values = (new[] {1, 2, 3}).Except(2).ToArray();
Assert.AreEqual(2, values.Length); Assert.AreEqual(2, values.Length);
Assert.AreEqual(1, values[0]); Assert.AreEqual(1, values[0]);
@@ -241,7 +257,7 @@ namespace ICD.Common.Utils.Tests.Extensions
[Test] [Test]
public void ToHashSetTest() public void ToHashSetTest()
{ {
IcdHashSet<int> values = (new[] { 1, 2, 3 }).ToHashSet(); IcdHashSet<int> values = (new[] {1, 2, 3}).ToHashSet();
Assert.AreEqual(3, values.Count); Assert.AreEqual(3, values.Count);
Assert.IsTrue(values.Contains(1)); Assert.IsTrue(values.Contains(1));
@@ -252,7 +268,7 @@ namespace ICD.Common.Utils.Tests.Extensions
[Test] [Test]
public void ToDictionaryIntTest() public void ToDictionaryIntTest()
{ {
Dictionary<int, int> values = (new[] { 1, 2, 3 }).ToDictionary(); Dictionary<int, int> values = (new[] {1, 2, 3}).ToDictionary();
Assert.AreEqual(3, values.Count); Assert.AreEqual(3, values.Count);
Assert.AreEqual(1, values[0]); Assert.AreEqual(1, values[0]);
@@ -263,7 +279,7 @@ namespace ICD.Common.Utils.Tests.Extensions
[Test] [Test]
public void ToDictionaryUIntTest() public void ToDictionaryUIntTest()
{ {
Dictionary<uint, int> values = (new[] { 1, 2, 3 }).ToDictionaryUInt(); Dictionary<uint, int> values = (new[] {1, 2, 3}).ToDictionaryUInt();
Assert.AreEqual(3, values.Count); Assert.AreEqual(3, values.Count);
Assert.AreEqual(1, values[0]); Assert.AreEqual(1, values[0]);
@@ -292,24 +308,24 @@ namespace ICD.Common.Utils.Tests.Extensions
[Test] [Test]
public void UnanimousTest() public void UnanimousTest()
{ {
Assert.IsTrue((new[] { true, true, true}).Unanimous()); Assert.IsTrue((new[] {true, true, true}).Unanimous());
Assert.IsTrue((new[] { false, false, false }).Unanimous()); Assert.IsTrue((new[] {false, false, false}).Unanimous());
Assert.IsFalse((new[] { false, true, false }).Unanimous()); Assert.IsFalse((new[] {false, true, false}).Unanimous());
Assert.IsFalse((new bool[] { }).Unanimous()); Assert.IsFalse((new bool[] { }).Unanimous());
} }
[Test] [Test]
public void UnanimousOtherTest() public void UnanimousOtherTest()
{ {
Assert.AreEqual("A", (new[] { "A", "A", "A" }).Unanimous("B")); Assert.AreEqual("A", (new[] {"A", "A", "A"}).Unanimous("B"));
Assert.AreEqual("C", (new[] { "B", "A", "B" }).Unanimous("C")); Assert.AreEqual("C", (new[] {"B", "A", "B"}).Unanimous("C"));
Assert.AreEqual("A", (new string[] { }).Unanimous("A")); Assert.AreEqual("A", (new string[] { }).Unanimous("A"));
} }
[Test] [Test]
public void PartitionTest() public void PartitionTest()
{ {
int[][] items = (new[] { 1, 2, 3, 4, 5, 6, 7, 8 }).Partition(3) int[][] items = (new[] {1, 2, 3, 4, 5, 6, 7, 8}).Partition(3)
.Select(p => p.ToArray()) .Select(p => p.ToArray())
.ToArray(); .ToArray();
@@ -334,13 +350,13 @@ namespace ICD.Common.Utils.Tests.Extensions
[Test] [Test]
public void GetAdjacentPairsTest() public void GetAdjacentPairsTest()
{ {
IEnumerable<int> a = new int[] {}; IEnumerable<int> a = new int[] { };
Assert.AreEqual(0, a.GetAdjacentPairs().Count()); Assert.AreEqual(0, a.GetAdjacentPairs().Count());
IEnumerable<int> b = new[] { 1 }; IEnumerable<int> b = new[] {1};
Assert.AreEqual(0, b.GetAdjacentPairs().Count()); Assert.AreEqual(0, b.GetAdjacentPairs().Count());
IEnumerable<int> c = new[] { 1, 2, 3 }; IEnumerable<int> c = new[] {1, 2, 3};
int[][] cPairs = c.GetAdjacentPairs().ToArray(); int[][] cPairs = c.GetAdjacentPairs().ToArray();
Assert.AreEqual(2, cPairs.Length); Assert.AreEqual(2, cPairs.Length);
@@ -350,17 +366,23 @@ namespace ICD.Common.Utils.Tests.Extensions
Assert.AreEqual(3, cPairs[1][1]); Assert.AreEqual(3, cPairs[1][1]);
} }
[Test]
public void GetClosestTest()
{
Assert.AreEqual(20, new[] {10, 15, 20, 30, 35}.GetClosest(i => i - 21));
}
[Test] [Test]
public void MinByTest() public void MinByTest()
{ {
Assert.AreEqual(1, new[] { 3, 6, 2, 7, 1 }.MinBy(i => i)); Assert.AreEqual(1, new[] {3, 6, 2, 7, 1}.MinBy(i => i));
} }
[Test] [Test]
public void MinByComparerTest() public void MinByComparerTest()
{ {
IComparer<int> comparer = new NegativeComparer(); IComparer<int> comparer = new NegativeComparer();
Assert.AreEqual(7, new[] { 3, 6, 2, 7, 1 }.MinBy(i => i, comparer)); Assert.AreEqual(7, new[] {3, 6, 2, 7, 1}.MinBy(i => i, comparer));
} }
private class NegativeComparer : IComparer<int> private class NegativeComparer : IComparer<int>
@@ -374,7 +396,7 @@ namespace ICD.Common.Utils.Tests.Extensions
[Test] [Test]
public void ExceptNullsTest() public void ExceptNullsTest()
{ {
IEnumerable<int?> sequence = new int?[] { 1, 2, null, 3, 4, null }; IEnumerable<int?> sequence = new int?[] {1, 2, null, 3, 4, null};
int[] result = sequence.ExceptNulls().ToArray(); int[] result = sequence.ExceptNulls().ToArray();
Assert.AreEqual(4, result.Length); Assert.AreEqual(4, result.Length);
@@ -387,14 +409,14 @@ namespace ICD.Common.Utils.Tests.Extensions
[Test] [Test]
public void SumTest() public void SumTest()
{ {
IEnumerable<byte> sequence = new byte[] { 1, 2, 3, 4 }; IEnumerable<byte> sequence = new byte[] {1, 2, 3, 4};
Assert.AreEqual(10, sequence.Sum()); Assert.AreEqual(10, sequence.Sum());
} }
[Test] [Test]
public void ConsolidateTest() public void ConsolidateTest()
{ {
string[] sequence = EnumerableExtensions.Consolidate(new[] { "A", "B", "B", "C" }).ToArray(); string[] sequence = EnumerableExtensions.Consolidate(new[] {"A", "B", "B", "C"}).ToArray();
Assert.AreEqual(3, sequence.Length, StringUtils.ArrayFormat(sequence)); Assert.AreEqual(3, sequence.Length, StringUtils.ArrayFormat(sequence));
Assert.AreEqual("A", sequence[0]); Assert.AreEqual("A", sequence[0]);
@@ -405,7 +427,7 @@ namespace ICD.Common.Utils.Tests.Extensions
[Test] [Test]
public void ConsolidateComparerTest() public void ConsolidateComparerTest()
{ {
string[] sequence = EnumerableExtensions.Consolidate(new[] { "A", "B", "B", "C" }, Comparer<string>.Default).ToArray(); string[] sequence = EnumerableExtensions.Consolidate(new[] {"A", "B", "B", "C"}, Comparer<string>.Default).ToArray();
Assert.AreEqual(3, sequence.Length, StringUtils.ArrayFormat(sequence)); Assert.AreEqual(3, sequence.Length, StringUtils.ArrayFormat(sequence));
Assert.AreEqual("A", sequence[0]); Assert.AreEqual("A", sequence[0]);
@@ -416,7 +438,7 @@ namespace ICD.Common.Utils.Tests.Extensions
[Test] [Test]
public void AnyAndAllTest() public void AnyAndAllTest()
{ {
IEnumerable<int> sequence = new[] { 1, 2, 3, 4 }; IEnumerable<int> sequence = new[] {1, 2, 3, 4};
Assert.IsTrue(sequence.AnyAndAll(i => i > 0)); Assert.IsTrue(sequence.AnyAndAll(i => i > 0));
Assert.IsFalse(sequence.AnyAndAll(i => i < 0)); Assert.IsFalse(sequence.AnyAndAll(i => i < 0));

View File

@@ -226,6 +226,24 @@ namespace ICD.Common.Utils.Extensions
/// <param name="match"></param> /// <param name="match"></param>
/// <returns></returns> /// <returns></returns>
public static int FindIndex<T>(this IEnumerable<T> extends, Predicate<T> match) public static int FindIndex<T>(this IEnumerable<T> extends, Predicate<T> match)
{
if (extends == null)
throw new ArgumentNullException("extends");
if (match == null)
throw new ArgumentNullException("match");
return extends.FindIndices(match).FirstOrDefault(-1);
}
/// <summary>
/// Returns the indices that match the predicate.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="extends"></param>
/// <param name="match"></param>
/// <returns></returns>
public static IEnumerable<int> FindIndices<T>(this IEnumerable<T> extends, Predicate<T> match)
{ {
if (extends == null) if (extends == null)
throw new ArgumentNullException("extends"); throw new ArgumentNullException("extends");
@@ -238,11 +256,9 @@ namespace ICD.Common.Utils.Extensions
foreach (T item in extends) foreach (T item in extends)
{ {
if (match(item)) if (match(item))
return index; yield return index;
index++; index++;
} }
return -1;
} }
/// <summary> /// <summary>
@@ -583,6 +599,18 @@ namespace ICD.Common.Utils.Extensions
} }
} }
/// <summary>
/// Gets the item from the sequence with the smallest calculated delta.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="extends"></param>
/// <param name="getDelta"></param>
/// <returns></returns>
public static T GetClosest<T>(this IEnumerable<T> extends, Func<T, int> getDelta)
{
return extends.MinBy(n => Math.Abs(getDelta(n)));
}
/// <summary> /// <summary>
/// Returns the minimal element of the given sequence, based on /// Returns the minimal element of the given sequence, based on
/// the given projection. /// the given projection.