SirJosh3917
SirJosh3917

Reputation: 309

C# Shift element of array untill 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, 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

Answers (5)

Pikoh
Pikoh

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

P. Roe
P. Roe

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

Romano Zumbé
Romano Zumbé

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

Alexandru Pupsa
Alexandru Pupsa

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

M.kazem Akhgary
M.kazem Akhgary

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

Related Questions