In python, I can take a list my_list and rotate the contents:
>>> my_list = list(range(10))
>>> my_list
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>
To rotate array, do a.Slice(1, null).Concat(a.Slice(null, 1))
.
Here's my stab at it. a.Slice(step: -1)
gives a reversed copy as a[::-1]
.
///
/// Slice an array as Python.
///
///
///
/// start index.
/// end index.
/// step
///
///
/// http://docs.python.org/2/tutorial/introduction.html#strings
/// +---+---+---+---+---+
/// | H | e | l | p | A |
/// +---+---+---+---+---+
/// 0 1 2 3 4 5
/// -6 -5 -4 -3 -2 -1
///
public static IEnumerable Slice(this T[] array,
int? start = null, int? end = null, int step = 1)
{
array.NullArgumentCheck("array");
// step
if (step == 0)
{
// handle gracefully
yield break;
}
// step > 0
int _start = 0;
int _end = array.Length;
// step < 0
if (step < 0)
{
_start = -1;
_end = -array.Length - 1;
}
// inputs
_start = start ?? _start;
_end = end ?? _end;
// get positive index for given index
Func toPositiveIndex = (int index, int length) =>
{
return index >= 0 ? index : index + length;
};
// start
if (_start < -array.Length || _start >= array.Length)
{
yield break;
}
_start = toPositiveIndex(_start, array.Length);
// end
if (_end < -array.Length - 1)
{
yield break;
}
if (_end > array.Length)
{
_end = array.Length;
}
_end = toPositiveIndex(_end, array.Length);
// slice
if (step > 0)
{
// start, end
if (_start > _end)
{
yield break;
}
for (int i = _start; i < _end; i += step)
{
yield return array[i];
}
}
else
{
// start, end
if (_end > _start)
{
yield break;
}
for (int i = _start; i > _end; i += step)
{
yield return array[i];
}
}
}
nunit tests:
[Test]
// normal cases
[TestCase(3, 5, 1, 3, 4)]
[TestCase(0, 5, 1, 0, 4)]
[TestCase(3, null, 1, 3, 9)]
[TestCase(0, null, 1, 0, 9)]
[TestCase(null, null, 1, 0, 9)]
[TestCase(0, 10, 1, 0, 9)]
[TestCase(0, int.MaxValue, 1, 0, 9)]
[TestCase(-1, null, 1, 9, 9)]
[TestCase(-2, null, 1, 8, 9)]
[TestCase(0, -2, 1, 0, 7)]
// corner cases
[TestCase(0, 0, 1, null, null)]
[TestCase(3, 5, 2, 3, 3)]
[TestCase(3, 6, 2, 3, 5)]
[TestCase(100, int.MaxValue, 1, null, null)]
[TestCase(int.MaxValue, 1, 1, null, null)]
[TestCase(-11, int.MaxValue, 1, null, null)]
[TestCase(-6, -5, 1, 4, 4)]
[TestCase(-5, -6, 1, null, null)]
[TestCase(-5, -5, 1, null, null)]
[TestCase(0, -10, 1, null, null)]
[TestCase(0, -11, 1, null, null)]
[TestCase(null, null, 100, 0, 0)]
// -ve step
[TestCase(null, null, -1, 9, 0)]
[TestCase(-7, -5, -1, null, null)]
[TestCase(-5, -7, -1, 5, 4)]
[TestCase(-5, -7, -2, 5, 5)]
[TestCase(-7, null, -1, 3, 0)]
public void Slice01(int? s, int? e, int i, int? first, int? last)
{
var a = new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
var slice = a.Slice(start: s, end: e, step: i).ToArray();
Print(slice);
if (first.HasValue)
{
Assert.AreEqual(first, slice.First());
}
if (last.HasValue)
{
Assert.AreEqual(last, slice.Last());
}
}