Скопировать массив в обратном направлении? Array.Copy? - PullRequest
4 голосов
/ 26 апреля 2010

У меня есть List<T>, который я хочу иметь возможность копировать в массив в обратном направлении, то есть начинать с List.Count и копировать, возможно, 5 элементов, начиная с конца списка и возвращаясь назад. Я мог бы сделать это с помощью простого обратного цикла for; однако, вероятно, есть более быстрый / более эффективный способ сделать это, поэтому я подумал, что должен спросить. Можно ли как-нибудь использовать Array.Copy?

Первоначально я использовал Queue, так как он выводит его в нужном мне порядке, но теперь мне нужно выдвинуть сразу несколько элементов в массив, и я подумал, что список будет быстрее.

Ответы [ 4 ]

3 голосов
/ 26 апреля 2010

Похоже, что Array.Reverse имеет собственный код для обращения к массиву, который иногда не применяется и возвращается к использованию простого цикла for. В моем тестировании Array.Reverse очень немного быстрее, чем простой цикл for. В этом тесте реверса массива 1000000 элементов 1000 раз Array.Reverse составляет около 600 мс, тогда как цикл for составляет около 800 мс.

Я бы не рекомендовал производительность в качестве причины для использования Array.Reverse. Это очень незначительное отличие, которое вы потеряете, как только вы загрузите его в List, который снова будет проходить через массив. Тем не менее, вам не следует беспокоиться о производительности, пока вы не профилируете свое приложение и не обнаружите узкие места в производительности.

    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;
        }
    }
1 голос
/ 26 апреля 2010

Невозможно сделать это быстрее, чем простой цикл for.

0 голосов
/ 26 апреля 2010

В одном из ваших комментариев:

В настоящее время мы извлекаем один результат и добавляем его в базу данных по одному

Существует большая разница между использованием цикла for для итерации в обратном направлении по List<T> и фиксацией записей в базе данных по одной за раз. Первый в порядке; никто не одобряет последнее.

Почему бы просто не повторить сначала - заполнить массив - и затем отправить этот массив в базу данных, все заполненные?

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);
0 голосов
/ 26 апреля 2010

Вы можете сделать это любым количеством способов, но самый быстрый способ - получить элементы именно так, как вы. Вы можете использовать Array.Reverse, Array.Copy и т. Д., Или вы можете использовать LINQ и методы расширения, и оба являются допустимыми альтернативами, но они не должны быть быстрее.

...