C # Shift element of array to specific point and pull specific element to front
My problem is that I want to have a specific element in the array, copy it to another variable, move the entire array up to that element only, and then put the element in front. In a good drawing, it will look like this.
[0, 1, 2, 3, 4, 5]
^
[0, 1, 2, null, 4, 5]
^ (3)
[null, 0, 1, 2, 4, 5]
^ (3)
[null, 0, 1, 2, 4, 5]
^ (3)
[3, 0, 1, 2, 4, 5]
^
I've already tried using a for loop to bring items to the front and then insert 3, but I'm afraid my way of doing this is not the most efficient or fastest way.
Here's what I've tried.
int elementAt = 3;
int[] array = { 0, 1, 2, 3, 4, 5 };
int mem = array[elementAt];
for (int i = elementAt; i > 0; i--)
array[i] = array[i - 1];
array[0] = mem;
I suspect something like Array.Copy might make it faster ...?
EDIT: Each individual answer below has its own uses in specific scenarios. There is no definitive answer for this question, let these results allow you to choose which method to use.
iterations, index, arraysize
HIGH, HIGH, HIGH
Speed for ShiftRightAt: 6616, ticks: 28007912
Speed for shiftlist: 3556, ticks: 15054635
Speed for arrayCopy: 1742, ticks: 7376152
Speed for MoveValueToFront: 67, ticks: 285901
LOW, LOW, HIGH
Speed for ShiftRightAt: 0, ticks: 28
Speed for shiftlist: 42, ticks: 180476
Speed for arrayCopy: 33, ticks: 142717
Speed for MoveValueToFront: 0, ticks: 67
HIGH, LOW, HIGH
Speed for ShiftRightAt: 0, ticks: 1399
Speed for shiftlist: 3624, ticks: 15341777
Speed for arrayCopy: 3177, ticks: 13449012
Speed for MoveValueToFront: 0, ticks: 926
LOW, HIGH, HIGH
Speed for ShiftRightAt: 73, ticks: 311428
Speed for shiftlist: 41, ticks: 174652
Speed for arrayCopy: 18, ticks: 79768
Speed for MoveValueToFront: 65, ticks: 277266
HIGH, HIGH, LOW
Speed for ShiftRightAt: 0, ticks: 1379
Speed for shiftlist: 0, ticks: 3902
Speed for arrayCopy: 0, ticks: 728
Speed for MoveValueToFront: 0, ticks: 914
LOW, LOW, LOW
Speed for ShiftRightAt: 0, ticks: 3
Speed for shiftlist: 0, ticks: 32
Speed for arrayCopy: 0, ticks: 11
Speed for MoveValueToFront: 0, ticks: 12
HIGH, LOW, LOW
Speed for ShiftRightAt: 0, ticks: 135
Speed for shiftlist: 0, ticks: 3850
Speed for arrayCopy: 0, ticks: 998
Speed for MoveValueToFront: 0, ticks: 840
LOW, HIGH, LOW
Speed for ShiftRightAt: 0, ticks: 15
Speed for shiftlist: 0, ticks: 16
Speed for arrayCopy: 0, ticks: 9
Speed for MoveValueToFront: 0, ticks: 39
Test method: https://pastebin.com/HKkixHGR
source to share
your beautiful drawing gives you exactly what you need to write.
public static void ShiftRightAt<T>(T[] array, int index)
{
if (index < 0 || index >= array.Length) return; // throw exception
var element = array[index]; // take out the element
for (int i = index; i > 0; i--)
{
array[i] = array[i - 1];
}
array[0] = element;
}
source to share
This is a using example Array.Copy
, so it should be fast enough:
int elementAt = 3;
int[] array = { 0, 1, 2, 3, 4, 5 };
int[] arr1=new int[array.Length];
arr1[0] = array[elementAt];
Array.Copy(array, 0, arr1, 1, elementAt);
Array.Copy(array, elementAt+1, arr1, elementAt+1, array.Length-elementAt-1);
//arr1={3, 0, 1, 2, 4, 5}
Edit
I was not happy with the results as I thought I Array.Copy
should be faster. I think this version improves speed significantly:
int saved = array[elementAt];
Array.Copy(array, elementAt + 1, array, elementAt, array.Length - elementAt - 1);
Array.Copy(array, 0, array, 1, array.Length - 1);
array[0] = saved;
source to share
Here's an extension method that you can use:
public static int[] MoveValueToFront(this int[] values, int searchValue)
{
if (values == null || values.Length == 0)
{
return values;
}
var rest = values.TakeWhile(v => v != searchValue).ToArray();
if (rest.Length == values.Length)
{
return values;
}
values[0] = searchValue;
rest.CopyTo(values, 1);
return values;
}
This will allow you to do this:
[TestMethod]
public void TestMoverExtension()
{
var testValues = new int[] { 0, 1, 2, 3, 4, 5 };
var result = testValues.MoveValueToFront(3);
CollectionAssert.AreEqual(new int[] { 3, 0, 1, 2, 4, 5 }, result);
}
source to share
If you can't (or don't want to) work with List
, you can also use the following:
public int[] moveElement(int[] array, int index)
{
int[] save = new int[] { array[index] };
var rest = array.Take(index).Concat(array.Skip(index + 1));
return save.Concat(rest).ToArray();
}
EDIT
If you need it for different data types, this is the general version:
public T[] moveElement<T>(T[] array, int index)
{
T[] save = new T[] { array[index] };
var rest = array.Take(index).Concat(array.Skip(index + 1));
return save.Concat(rest).ToArray();
}
source to share