Подтвердить что ты не робот

Каков наиболее эффективный способ обращения к массиву в Javascript?

Недавно меня спросили, что было самым эффективным способом обращения к массиву в Javascript. На данный момент я предложил использовать цикл for и возиться с массивом, но затем понял, что существует собственный метод Array.reverse().

Для любопытства, может ли кто-нибудь помочь мне изучить это, показывая примеры или указывая в правильном направлении, чтобы я мог прочитать это? Любые предложения относительно того, как измерить производительность, также были бы удивительными.

4b9b3361

Ответ 1

На основе этой настройки:

var array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
var length = array.length;

Array.reverse(); является первым или вторым самым медленным!

Тесты здесь: http://jsperf.com/js-array-reverse-vs-while-loop/5

Во всех браузерах swap-контуры быстрее. Существует два общих типа алгоритмов подкачки (см. Wikipedia), каждый из которых имеет два варианта.

Двумя типами подкатегорий являются временный своп и сводка XOR.

Два варианта обрабатывают индексные вычисления по-разному. Первая вариация сравнивает текущий левый индекс и правый индекс, а затем уменьшает правый индекс массива. Вторая вариация сравнивает текущий левый индекс и длину, разделенную на половину, а затем пересчитывает правый индекс для каждой итерации.

Вы можете увидеть или не увидеть огромные различия между этими двумя вариантами. Например, в Chrome 18 первые варианты временного свопа и замены XOR на 60% медленнее, чем во втором варианте, но в Opera 12 оба варианта временного свопа и обмена XOR имеют схожую производительность.

Временная свопа:

Первая вариация:

function temporarySwap(array)
{
    var left = null;
    var right = null;
    var length = array.length;
    for (left = 0, right = length - 1; left < right; left += 1, right -= 1)
    {
        var temporary = array[left];
        array[left] = array[right];
        array[right] = temporary;
    }
    return array;
}

Вторая вариация:

function temporarySwapHalf(array)
{
    var left = null;
    var right = null;
    var length = array.length;
    for (left = 0; left < length / 2; left += 1)
    {
        right = length - 1 - left;
        var temporary = array[left];
        array[left] = array[right];
        array[right] = temporary;
    }
    return array;
}

XOR swap:

Первая вариация:

function xorSwap(array)
{
    var i = null;
    var r = null;
    var length = array.length;
    for (i = 0, r = length - 1; i < r; i += 1, r -= 1)
    {
        var left = array[i];
        var right = array[r];
        left ^= right;
        right ^= left;
        left ^= right;
        array[i] = left;
        array[r] = right;
    }
    return array;
}

Вторая вариация:

function xorSwapHalf(array)
{
    var i = null;
    var r = null;
    var length = array.length;
    for (i = 0; i < length / 2; i += 1)
    {
        r = length - 1 - i;
        var left = array[i];
        var right = array[r];
        left ^= right;
        right ^= left;
        left ^= right;
        array[i] = left;
        array[r] = right;
    }
    return array;
}

Существует еще один метод подкачки, называемый назначением деструктуризации: http://wiki.ecmascript.org/doku.php?id=harmony:destructuring

Назначение деструктуризации:

Первая вариация:

function destructuringSwap(array)
{
    var left = null;
    var right = null;
    var length = array.length;
    for (left = 0, right = length - 1; left < right; left += 1, right -= 1)
    {
        [array[left], array[right]] = [array[right], array[left]];
    }
    return array;
}

Вторая вариация:

function destructuringSwapHalf(array)
{
    var left = null;
    var right = null;
    var length = array.length;
    for (left = 0; left < length / 2; left += 1)
    {
        right = length - 1 - left;
        [array[left], array[right]] = [array[right], array[left]];
    }
    return array;
}

В настоящее время алгоритм, использующий назначение деструктуризации, является самым медленным из всех. Он еще медленнее, чем Array.reverse();. Однако алгоритмы, использующие назначения деструктурирования и методы Array.reverse();, являются кратчайшими примерами, и они выглядят чище. Я надеюсь, что их производительность улучшится в будущем.


Еще одно упоминание о том, что современные браузеры улучшают производительность массивов push и splice.

В Firefox 10 этот алгоритм цикла for с использованием массива push и splice конкурирует с алгоритмами временного свопинга и XOR-подкачки.

for (length -= 2; length > -1; length -= 1)
{
    array.push(array[length]);
    array.splice(length, 1);
}

Однако вы, вероятно, должны придерживаться алгоритмов цикла подкачки, пока многие из других браузеров не совпадают или не превысят производительность своего массива push и splice.

Ответ 2

Нативные методы всегда быстрее.

Поэтому используйте Array.reverse, где это возможно. В противном случае реализация, которая работает в O(1), была бы лучше;)

В противном случае просто используйте что-то вроде этого

var reverse = function(arr) {
   var result = [],
       ii = arr.length;
   for (var i = ii - 1;i !== 0;i--) {
       result.push(arr[i]);
   }
   return result;
}

Benchmark!

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

for(var i = ii - 1; i !== 0;i--) быстрее, чем var i = ii - 1;for(;i-- !== 0;)

Ответ 3

I открыл ошибку Firefox о медленной обратной производительности в Firefox. Кто-то из Mozilla просмотрел контрольную отметку, используемую в принятом сообщении, и говорит, что это довольно вводит в заблуждение. В своем анализе собственный метод лучше вообще реверсирует массивы. (Как и должно быть!)

Ответ 4

Простым способом вы можете сделать это с помощью карты.

let list = [10, 20, 30, 60, 90]
let reversedList = list.map((e, i, a)=> a[(a.length -1) -i]) // [90, 60...]

Ответ 5

Функции обмена являются самыми быстрыми. Здесь обратная функция, которую я написал, немного похожа на функции обмена, упомянутые выше, но работает быстрее.

function reverse(array) {
  var first = null;
  var last = null;
  var tmp = null;
  var length = array.length;

  for (first = 0, last = length - 1; first < length / 2; first++, last--) {
    tmp = array[first];
    array[first] = array[last];
    array[last] = tmp;
  }
}

Здесь вы можете найти бенчмаркинг http://jsperf.com/js-array-reverse-vs-while-loop/19

Ответ 6

Поскольку никто не придумал его и не завершил список способов обращения к массиву...

array.sort(function() {
    return 1;
})

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

http://jsperf.com/js-array-reverse-vs-while-loop/53

Ответ 7

Здесь приведен пример java http://www.leepoint.net/notes-java/data/arrays/arrays-ex-reverse.html, показывающий, как изменить массив. Очень легко конвертировать в javascript.

Я бы предложил использовать что-то, что просто захватывает время до вызова функции и после вызова функции. Который когда-либо занимает наименьшее время/часы, будет самым быстрым.

Ответ 8

Если вы хотите скопировать реверсивную версию массива и сохранить оригинал как есть:

a = [0,1,2,3,4,5,6,7,8,9];
b = []
for(i=0;i<a.length;i++){
    b.push(a.slice(a.length-i-1,a.length-i)[0])
}

Выход b:

[ 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

Ответ 9

Вот еще один пример для постоянного изменения массива, изменяющего его элементы:

var theArray = ['a', 'b', 'c', 'd', 'e', 'f'];

function reverseArrayInPlace(array) {
  for (var i = array.length - 1; i >= 0; i -= 1) {
    array.push(array[i]);
  }
  array.splice(0, array.length / 2);
  return array;
};
reverseArrayInPlace(theArray);
console.log(theArray); // -> ["f", "e", "d", "c", "b", "a"]

Ответ 10

Вот несколько трюков, которые я нашел. Кредит отправляется Codemanx за оригинальное решение

array.sort(function() {
   return 1;
})

В Typescript это можно упростить до одной строки

array.sort(() => 1)

var numbers = [1,4,9,13,16];

console.log(numbers.sort(() => 1));

Ответ 11

Другое предложение, аналогичное вышеизложенному, но вместо этого использует сращивание:

var myArray=["one","two","three","four","five","six"];
console.log(myArray);
for(i=0;i<myArray.length;i++){
myArray.splice(i,0,myArray.pop(myArray[myArray.length-1]));
}
console.log(myArray);

Ответ 12

Это самый эффективный и чистый способ обратного преобразования массива с помощью тернарного оператора.

function reverse(arr) {
  return arr.length < 2 ? arr : [arr.pop()].concat(reverse(arr));
}
console.log(reverse([4, 3, 3, 1]));

Ответ 13

Я нашел простой способ сделать это с помощью .slice(). reverse()

var yourArray = ["first", "second", "third", "...", "etc"]
var reverseArray = yourArray.slice().reverse()

console.log(reverseArray)

Вы получите

["etc", "...", "third", "second", "first"]