views:

104

answers:

4

I have a List<T> that I want to be able to copy to an array backwards, meaning start from List.Count and copy maybe 5 items starting at the end of the list and working its way backwards. I could do this with a simple reverse for loop; however there is probably a faster/more efficient way of doing this so I thought I should ask. Can I use Array.Copy somehow?

Originally I was using a Queue as that pops it off in the correct order I need, but I now need to pop off multiple items at once into an array and I thought a list would be faster.

+1  A: 

It is not possible to do this faster than a simple for loop.

SLaks
A: 

You can accomplish it any number of ways, but the fastest way is get the elements in exactly the manner you are. You can use Array.Reverse, Array.Copy, etc., or you can use LINQ and extension methods, and both are valid alternatives, but they shouldn't be any faster.

Anthony Pegram
+1  A: 

Looks like Array.Reverse has native code for reversing an array which sometimes doesn't apply and would fall back to using a simple for loop. In my testing Array.Reverse is very slightly faster than a simple for loop. In this test of reversing a 1,000,000 element array 1,000 times, Array.Reverse is about 600ms whereas a for-loop is about 800ms.

I wouldn't recommend performance as a reason to use Array.Reverse though. It's a very minor difference which you'll lose the minute you load it into a List which will loop through the array again. Regardless, you shouldn't worry about performance until you've profiled your app and identified the performance bottlenecks.

    public static void Test()
    {
        var a = Enumerable.Range(0, 1000000).ToArray();

        var stopwatch = Stopwatch.StartNew();

        for(int i=0; i<1000; i++)
        {
            Array.Reverse(a);
        }

        stopwatch.Stop();

        Console.WriteLine("Elapsed Array.Reverse: " + stopwatch.ElapsedMilliseconds);

        stopwatch = Stopwatch.StartNew();

        for (int i = 0; i < 1000; i++)
        {
            MyReverse(a);
        }

        stopwatch.Stop();

        Console.WriteLine("Elapsed MyReverse: " + stopwatch.ElapsedMilliseconds);
    }

    private static void MyReverse(int[] a)
    {
        int j = a.Length - 1;
        for(int i=0; i<j; i++, j--)
        {
            int z = a[i];
            a[i] = a[j];
            a[j] = z;
        }
    }
Sam
I have identified it as a huge performance bottleneck. Currently we are pulling out one result and committing it to a database one at a time, but i'm going to make it commit a range at a time, but it needs to be in order. That is why i am doing it.
daniel
@daniel, but I assume the bottleneck is executing one query against the database at a time, not reversing the array.
Sam
true, wasn't thinking straight xD
daniel
A: 

In one of your comments:

Currently we are pulling out one result and committing it to a database one at a time

There is a big difference between using a for loop to iterate backwards over a List<T> and committing records to a database one at a time. The former is fine; nobody's endorsing the latter.

Why not just iterate first--to populate an array--and then send that array into the database, all populated?

var myArray = new T[numItemsYouWantToSend];

int arrayIndex = 0;
for (int i = myList.Count - 1; arrayIndex < myArray.Length; --i) {
    if (i < 0) break;
    myArray[arrayIndex++] = myList[i];
}

UpdateDatabase(myArray);
Dan Tao