Andy Evans
Andy Evans

Reputation: 1

How do I shift items in an array in C#?

Let's say that I have an array of strings like this:

1, 2, 3, 4, 5, 6, 7, 8

and I want to shift the elements of the array such that

  1. The first element always remains fixed
  2. Only the remaining elements get shifted like so ...
  3. The last element in the array becomes the 2nd element and is shifted through the array with each pass.

Pass #1: 1, 2, 3, 4, 5, 6, 7, 8
Pass #2: 1, 8, 2, 3, 4, 5, 6, 7
Pass #3: 1, 7, 8, 2, 3, 4, 5, 6
Pass #4: 1, 6, 7, 8, 2, 3, 4, 5

Any assistance would be greatly appreciated.

Upvotes: 0

Views: 2876

Answers (6)

Anthony Pegram
Anthony Pegram

Reputation: 126982

This is similar to Josh Einstein's but it will do it manually and will allow you to specify how many elements to preserve at the beginning.

static void ShiftArray<T>(T[] array, int elementsToPreserve)
{
    T temp = array[array.Length - 1];

    for (int i = array.Length - 1; i > elementsToPreserve; i--)
    {
        array[i] = array[i - 1];
    }

    array[elementsToPreserve] = temp;
}

Consumed:

int[] array = { 1, 2, 3, 4, 5, 6, 7, 8 };
ShiftArray(array, 2);

First pass: 1 2 8 3 4 5 6 7

Upvotes: 0

Damian Powell
Damian Powell

Reputation: 8775

Define this:

public static class Extensions
{
    public static IEnumerable<T> Rotate<T>(this IEnumerable<T> enuml)
    {
        var count = enuml.Count();
        return enuml
            .Skip(count - 1)
            .Concat(enuml.Take(count - 1));
    }

    public static IEnumerable<T> SkipAndRotate<T>(this IEnumerable<T> enuml)
    {
        return enum
            .Take(1)
            .Concat(
                enuml.Skip(1).Rotate()
            );
    }
}

Then call it like so:

var array = new [] { 1, 2, 3, 4, 5, 6, 7, 8 };

var pass1 = array.SkipAndRotate().ToArray();
var pass2 = pass1.SkipAndRotate().ToArray();
var pass3 = pass2.SkipAndRotate().ToArray();
var pass4 = pass3.SkipAndRotate().ToArray();

There's some repeated code there that you might want to refactor. And of course, I haven't compiled this so caveat emptor!

Upvotes: 0

DRapp
DRapp

Reputation: 48179

Although sounds like homework like others suggest, if changing to a List<>, you can get what you want with the following...

List<int> Nums2 = new List<int>();
for( int i = 1; i < 9; i++ )
   Nums2.Add(i);

for (int i = 1; i < 10; i++)
{
    Nums2.Insert( 1, Nums2[ Nums2.Count -1] );
    Nums2.RemoveAt(Nums2.Count -1);
}

Upvotes: 0

Josh
Josh

Reputation: 69282

Probably the fastest way to do this in C# is to use Array.Copy. I don't know much about pointers in C# so there's probably a way of doing it that's even faster and avoids the array bounds checks and such but the following should work. It makes several assumptions and doesn't check for errors but you can fix it up.

void Shift<T>(T[] array) {
    T last = array[array.Length-1];
    Array.Copy(array, 1, array, 2, array.Length-2);
    array[1]=last;
}

EDIT
Optionally, there is Buffer.BlockCopy which according to this post performs fewer validations but internally copies the block the same way.

Upvotes: 3

dtb
dtb

Reputation: 217401

Because this looks like homework, I'm posting an unnecessary complex, but very hip LINQ solution:

int[] array = new int[] { 1, 2, 3, 4, 5, 6, 7, 8 };

int[] result = array.Take(1)
                    .Concat(array.Reverse().Take(1))
                    .Concat(array.Skip(1).Reverse().Skip(1).Reverse())
                    .ToArray();

Upvotes: 7

Kevin Anderson
Kevin Anderson

Reputation: 7010

Because this looks like homework, I'm not going to solve it for you, but I have a couple of suggestions:

  1. Remember to not overwrite data if it isn't somewhere else already. You're going to need a temporary variable.
  2. Try traversing the array from the end to the beginning. The problem is probably simpler that way, though it can be done from front-to-back.
  3. Make sure your algorithm works for an arbitrary-length array, not just one that's of size 8, as your example gave.

Upvotes: 1

Related Questions