Reputation: 309
My problem is that I want to have a specific element in the array, copy it to another variable, shift the entire array right only up unto that element, and then put the element at the front. In a nice drawing, It'd 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 to use a for loop to bring the elements to the front and then insert the 3, but I fear that my way of doing it isn't 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'm suspecting something like Array.Copy could do it faster...?
EDIT: Every single answer down below has their own uses in specific scenarios. There is no definitive answer for this question, let these results let you 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
Method of testing: https://pastebin.com/HKkixHGR
Upvotes: 3
Views: 113
Reputation: 7703
This is an example using 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 satisfied with the results, as i thought the Array.Copy
should be faster. I think this version improves speed a lot:
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;
Upvotes: 1
Reputation: 2117
Here's an extension method that you could 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;
}
Which would 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);
}
Upvotes: 1
Reputation: 8079
If you can't (or don't want to) work with List
you could 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 this for different data types this is a generic 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();
}
Upvotes: 0
Reputation: 1868
It's easier using a list. After that, convert it back to an array.
var array = new int[] { 0, 1, 2, 3, 4, 5 };
var list = array.ToList();
list.Remove(3);
list.Insert(0, 3);
array = list.ToArray();
Upvotes: 1
Reputation: 19149
your nice drawing gives 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;
}
Upvotes: 3