The following are correct answers for non-linear sequences and are effective, for example:
const int PivotValue = 5; const int RangeSize = 2; int[] enumerable = new[] { 0, 1, 2, 3, 4, 5, 600, 700, 800, 900, 1000 }; IEnumerable<int> range = enumerable.PivotRange(PivotValue, RangeSize);}
Code - General Version
public static IEnumerable<T> PivotRange<T>( this IEnumerable<T> source, T pivot, int size) where T : IComparable<T> { T[] left = new T[size]; int lCount = 0, rCount = 0; IEnumerator<T> enumerator = source.GetEnumerator(); while (enumerator.MoveNext()) { T item = enumerator.Current; if (item.CompareTo(pivot) == 0) { int start = lCount > size ? lCount % size : 0; int end = Math.Min(size, lCount); for (int i = start; i < start + end; i++) yield return left[i % size]; yield return pivot; while (enumerator.MoveNext() && rCount++ < size) yield return enumerator.Current; break; } if (size <= 0) continue; left[lCount++ % size] = item; } }
Update - unit tests
[Test] public void Linear() { const int PivotValue = 5; const int RangeSize = 2; int[] enumerable = new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; int[] range = enumerable.PivotRange(PivotValue, RangeSize).ToArray(); CollectionAssert.AreEqual(new[] { 3, 4, 5, 6, 7 }, range); } [Test] public void NonLinear() { const int PivotValue = 5; const int RangeSize = 2; int[] enumerable = new[] { 0, 1, 2, 3, 4, 5, 600, 700, 800, 900, 1000 }; int[] range = enumerable.PivotRange(PivotValue, RangeSize).ToArray(); CollectionAssert.AreEqual(new[] { 3, 4, 5, 600, 700 }, range); } [Test] public void NoLeft() { const int PivotValue = 5; const int RangeSize = 2; int[] enumerable = new[] { 5, 600, 700, 800, 900, 1000 }; int[] range = enumerable.PivotRange(PivotValue, RangeSize).ToArray(); CollectionAssert.AreEqual(new[] { 5, 600, 700 }, range); } [Test] public void NoRight() { const int PivotValue = 5; const int RangeSize = 2; int[] enumerable = new[] { 0, 1, 2, 3, 4, 5 }; int[] range = enumerable.PivotRange(PivotValue, RangeSize).ToArray(); CollectionAssert.AreEqual(new[] { 3, 4, 5 }, range); } [Test] public void ZeroRange() { const int PivotValue = 5; const int RangeSize = 0; int[] enumerable = new[] { 0, 1, 2, 3, 4, 5 }; int[] range = enumerable.PivotRange(PivotValue, RangeSize).ToArray(); CollectionAssert.AreEqual(new[] { 5 }, range); } [Test] public void LeftShorterThanRange() { const int PivotValue = 5; const int RangeSize = 2; int[] enumerable = new[] { 4, 5, 6, 7, 8 }; int[] range = enumerable.PivotRange(PivotValue, RangeSize).ToArray(); CollectionAssert.AreEqual(new[] { 4, 5, 6, 7 }, range); } [Test] public void RightShorterThanRange() { const int PivotValue = 5; const int RangeSize = 2; int[] enumerable = new[] { 2, 3, 4, 5, 6, }; int[] range = enumerable.PivotRange(PivotValue, RangeSize).ToArray(); CollectionAssert.AreEqual(new[] { 3, 4, 5, 6 }, range); }