以下给出了非线性序列的正确答案并且是有效的,例如:
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);}
//3, 4, 5, 600, 700.
代码 - 通用版本
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;
}
}
更新 - 单元测试
[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);
}