Does code exist, for shifting List elements to left or right by specified amount, in C#?
It is tricky code, it will take some time to write and test special cases, I would rather reuse something if it exists.
Thanks
Does code exist, for shifting List elements to left or right by specified amount, in C#?
It is tricky code, it will take some time to write and test special cases, I would rather reuse something if it exists.
Thanks
Something like this for shift left...
public static void ShiftLeft<T>(List<T> lst, int shifts)
{
for (int i = shifts; i < lst.Count; i++)
{
lst[i - shifts] = lst[i];
}
for (int i = lst.Count - shifts; i < lst.Count; i++)
{
lst[i] = default(T);
}
}
For shift right it's a little more tricky, because we must copy in reverse
public static void ShiftRight<T>(List<T> lst, int shifts)
{
for (int i = lst.Count - shifts - 1; i >= 0; i--)
{
lst[i + shifts] = lst[i];
}
for (int i = 0; i < shifts; i++)
{
lst[i] = default(T);
}
}
With arrays it's a lot more simple, because Array
has very powerful methods:
public static void ShiftLeft<T>(T[] arr, int shifts)
{
Array.Copy(arr, shifts, arr, 0, arr.Length - shifts);
Array.Clear(arr, arr.Length - shifts, shifts);
}
public static void ShiftRight<T>(T[] arr, int shifts)
{
Array.Copy(arr, 0, arr, shifts, arr.Length - shifts);
Array.Clear(arr, 0, shifts);
}
And yes, Array.Copy
is protected against overleap: If sourceArray and destinationArray overlap, this method behaves as if the original values of sourceArray were preserved in a temporary location before destinationArray is overwritten.
Below are a couple of extension methods that will shift the list either right or left. The methods will return a list.
public static class ShiftList
{
public static List<T> ShiftLeft<T>(this List<T> list, int shiftBy)
{
if (list.Count <= shiftBy)
{
return list;
}
var result = list.GetRange(shiftBy, list.Count-shiftBy);
result.AddRange(list.GetRange(0,shiftBy));
return result;
}
public static List<T> ShiftRight<T>(this List<T> list, int shiftBy)
{
if (list.Count <= shiftBy)
{
return list;
}
var result = list.GetRange(list.Count - shiftBy, shiftBy);
result.AddRange(list.GetRange(0, list.Count - shiftBy));
return result;
}
}
Here's an example of how to call it.
class Program
{
static void Main(string[] args)
{
List<int> test = Enumerable.Range(0, 10).ToList();
test = test.ShiftLeft(1);
PrintList(test);
Console.WriteLine("");
PrintList(test.ShiftRight(2));
Console.ReadLine();
}
private static void PrintList(List<int> test)
{
for (int i = 0; i < test.Count; i++)
{
Console.WriteLine(test[i]);
}
}
}
Keep it simple by taking the first part and second part and flipping them. Same thing but flip other way for the ShiftRight
public static List<int> ShiftLeft(List<int> a, int d)
{
if (a.Count > d)
{
var beginingPart = a.GetRange(0, d);
var remainingPart = a.GetRange(d, a.Count - d);
return remainingPart.Concat(beginingPart).ToList();
}
else if (a.Count < d)
{
var mod = d % a.Count;
if (mod != 0)
{
return rotLeft(a, mod);
}
}
return a;
}
Given that "iterations" is the times you want to shift and "numbers" is the List
Shift left:
static void ShiftLeft(int iterations)
{
for (int i = 0; i < iterations; i++)
{
numbers.Add(numbers[0]);
numbers.RemoveAt(0);
}
}
ShiftRight:
static void ShiftRight(int iterations)
{
for (int i = 0; i < iterations; i++)
{
numbers.Insert(0, numbers[numbers.Count - 1]);
numbers.RemoveAt(numbers.Count - 1);
}
}