Jared Forth
Jared Forth

Reputation: 1637

Moving the first array element to end in C#

This is a basic question ( I am new to C#), but is there an efficient way to move the first element to the end of the array in C#?

I found this question, which describes the .rotate method in ruby, but I have been unable to find a similar method in C#.

If I have an array:

[1, 2, 3, 4, 5]

Is there a function in C# that returns:

[2, 3, 4, 5, 1]

Thanks in advance!

EDIT: Answer

The best solution is to use LinkedList<T> as many of you suggested and as shown in Alex's answer. His suggested solution was using:

list.AddLast(list.RemoveFirst());

which can be run in a for loop:

    void func<T>(LinkedList<T> list, int rotate) {
    for(var i = 0; i < rotate; i++) {
       list.AddLast(list.RemoveFirst());
    }
}

Thank you all for your help!

Upvotes: 5

Views: 14718

Answers (8)

Alex
Alex

Reputation: 1957

If you use LinkedList<T> instead of array<T> you could just use this:

list.AddLast(list.RemoveAndGetFirst());

Edit: RemoveAndGetFirst() can be an extension like:

LinkedListNode<T> elem = list.First;
list.RemoveFirst();
return elem;

Complexity O(1). When you perform this multiple times:

void func<T>(LinkedList<T> list, int rotate) {
    for(var i = 0; i < rotate; i++) {
       list.AddLast(list.RemoveFirst());
    }
}

You will have a complexity of O(N) [where N is the number of rotations]. This is, performance wise, the best solution.

If you really need to use arrays this could be a naiv solution:

var tmp = list[0];
for(var i = 1; i < list.Length; i++) {
   list[i - 1] = list[i];
}
list[list.Length - 1] = tmp;

(Be aware there are no range checks)

But this will be very time consuming if you need to do this often. If you perform this multiple times:

void func<T>(T[] list, int rotate) {
    for(var j = 0; j < rotate; j++) {
       var tmp = list[0];
       for(var i = 1; i < list.Length; i++) {
           list[i - 1] = list[i];
       }
       list[list.Length - 1] = tmp;
    }
}

You will end up with O(N^2) = O(N * M) [where N is the number of elements and M the number of rotations]. This would be really bad. A better approach, if you know in advance you'll perform this often would be:

void func<T>(T[] list, int rotate {
    for(var j = 0; j < list.Length; j++) {
        var tmp = list[j];
        var ix = (rotate + j) % list.Length;
        list[j] = list[ix];
        list[ix] = tmp;
    }
}

Which will result in O(N) [where N is the number of elements].

As others already suggested, it's a good idea to write an extension method if you need this at multiple locations.

Upvotes: 7

aswzen
aswzen

Reputation: 1642

Try this one..

using System;

public class Program
{   
    public static  int[] arrData = new int[5]{1,2,3,4,5};

    public static void Main()
    {
        Console.WriteLine("\nOriginal array\n");
        foreach(var item in arrData)
        {
            Console.WriteLine(item.ToString());
        }
        Console.WriteLine("\nShift to last\n");
        arrData = shiftLast(arrData);
        foreach(var item in arrData)
        {
            Console.WriteLine(item.ToString());
        }
    }

    public static int[] shiftLast(int[] arr)
    {
        int last = arr[arr.Length - 1];
        int first= arr[0];
        arr[arr.Length - 1] = first;
        arr[0] = last;
        return arr;
    }
}

Try to run here

Cheers

Upvotes: 2

Peter B
Peter B

Reputation: 24280

It's starting to look like Code Golf now :-) so here's my contribution:

var x = new[] { 1, 2, 3, 4, 5 };

var y = Enumerable.Range(1, x.Length).Select(i => x[i % x.Length]).ToArray();

Upvotes: 3

phuzi
phuzi

Reputation: 13079

Using Array.Copy to copy elements to itself just shifted ;)

var array = new int[]{1, 2, 3, 4, 5};

var head = array[0];
Array.Copy(array, 1, array, 0, array.Length- 1);
array[array.Length - 1] = head;

And as an extension method returning a new array just like the Ruby version

static class ArrayRotateExtensions {
    public static int[] Rotate(this int[] arr, int offset) {
        var l = arr.Length;
        var rot = new int[l];

        if (offset == 0) {
            Array.Copy(arr, 0, rot, 0, l);
            return rot;
        }

        // constrain rotations greater than array length, it's the same result anyway
        offset = offset % l;

        // negative rotation is equal to positive rotation length - offset
        if (offset < 0) {
            offset += l;
        }

        Array.Copy(arr, offset, rot, 0, l - offset);
        Array.Copy(arr, 0, rot, l - offset, offset);

        return rot;
    }
}

This will allow you to do

var array = new int[]{1, 2, 3, 4, 5};
var rotated = array.Rotate(1);

Plus rotation by any arbitrary amount.

Only downside is you'd have to add a version for every array type you'd like to use it on.

Upvotes: 4

Fabjan
Fabjan

Reputation: 13676

The reason why there is no function like that in LINQ is most likely that people who developed LINQ didn't think it's something that is an absolute must...

If you really need that you can create an extension method. Something along the lines of:

    public static IEnumerable<T> Rotate<T>(this IEnumerable<T> elements, int number)
    {
        var elemetsList = elements as IList<T> ?? elements.ToList();
        var list = new List<T>(elemetsList.Count);

        if (number > elemetsList.Count - 1)
        {
            throw new ArgumentException(nameof(number));
        }

        for (int i = number; i < elemetsList.Count; i++)
        {
            list.Add(elemetsList[i]);
        }

        for (int i = 0; i < number; i++)
        {
            list.Add(elemetsList[i]);
        }

        return list;
    }

And use it:

var arr = new int[] {1, 2, 3, 4, 5};
int[] result = arr.Rotate(1).ToArray();
int[] result2 = arr.Rotate(3).ToArray();

Output:

2 3 4 5 1

4 5 1 2 3

This solution is fairly efficient. For an array 500 000 in length it took only 7ms on my machine to execute.

Upvotes: 2

Pinx0
Pinx0

Reputation: 1258

As far as I know there isn't such method for an array. If you do this often perhaps you should consider using a different object (List<T>, Stack<T>, etc).

But even with an array you can implement simple functionality like this using extension methods:

public static int[] MoveFirstToLast (this int[] obj)
{
    int movedValue = obj[0];
    (int i = 1; i < obj.Length; i++)
    {
        obj[i - 1] = obj[i];
    }
    obj[obj.Length - 1] = movedValue;
    return obj;
}

And then the use is just:

int[] myArray = //whatever;
int[] changedArray = myArray.MoveFirstToLast();

Upvotes: 1

Rajib Chy
Rajib Chy

Reputation: 880

Maybe like this -

        static void Main( string[] args ) {
            Console.WriteLine(string.Join(", ", getArray(new int[] { 1, 2, 3, 4, 5 })));
            Console.Read();
            return;
        }
        static int[] getArray( int[] arr ) {
            List<int> O = new List<int>();
            for (int x = 1, l = arr.Length; x < l; x++) {
                O.Add(arr[x]);
            }
            O.Add(arr[0]);
            return O.ToArray();
        }

Upvotes: 1

Magnus
Magnus

Reputation: 47036

There are many ways to achieve this. One way would be:

var result = arr.Skip(1).Concat(arr.Take(1))

Upvotes: 11

Related Questions