2013-12-12 3 views
0

Будет ли быстрее использоватьНаиболее эффективный способ вычисления последнего элемента в массиве JavaScript?

var lastelement = myarray[myarray.length - 1]; 

или

var lastelement = myarray.reverse()[0]; 

и почему?

+9

Обратный массив, чтобы получить последний элемент? Шутки в сторону ? Кстати, вы, вероятно, забыли скобки. –

+6

Обратите внимание, что вместо запроса SO вы можете протестировать самостоятельно, например, используя http://jsperf.com –

+0

предупреждение об оптимизации! – rlemon

ответ

4

Просто подумайте об этом.

Если вы знаете, как долго массив, то намного быстрее, чтобы просто получить последнее значение, чем вычислять обратное!

0

Быстро получить доступ к элементу по его индексу, так как он должен иметь сложность O (1). С другой стороны, реверсив массив, а затем доступ к первому индексу, будет иметь как минимум сложность O (n), в зависимости от того, как реализуется алгоритм реверсирования.

+0

Сложность - это не скорость. Конечно, быстрее запросить длину, но это не доказательство. –

+0

edit: Ну, на самом деле он попросил самый быстрый способ. прости. Могу ли я спросить вас, почему сложность не означает скорость кстати? – luizrogeriocn

+1

@luizrogeriocn: Иногда наивные решения с худшей сложностью быстрее, чем более эффективные алгоритмы для небольших входов, а иногда и для удивительно больших входов. – Bergi

1

Я возьму это под другим углом, чем здесь был дан ответ. Скорее всего, вы просто хотите получить последний элемент, вы не хотите ничего делать с самим массивом. Если вы используете array.reverse, чтобы получить последний элемент, вы фактически меняете массив (вероятно, неприятный побочный эффект в вашем случае).

var myArray = [.....]; // some array 
var lastElement = myArray.reverse()[0]; // get the last element 
var firstElement = myArray[0]; // tricked you! This is now the same as 
           // lastElement because the myArray object 
           // in memory has been reversed. 

Так что если вы хотите получить последний элемент без изменения массива вы должны сделать это:

var myArray = [.....]; // some array 
var lastElement = myArray.slice().reverse()[0]; // copy and get the last element 
var firstElement = myArray[0]; // this is the correct first element 

Довольно очевидно, какой путь является более эффективным в настоящее время.

+0

Почему определение lastElement в терминах измененного myArray меняет определение самого myArray? Это как сказать var foo = 2, а затем сказать var bar = foo + 1 и ожидать foo === 3 сейчас. Я что-то упускаю? –

+0

Метод 'reverse()' изменяет сам объект массива, а не просто возвращает новый, обратный массив (он возвращает тот же, мутированный массив), что может привести к непреднамеренным последствиям. Однако ваше недоразумение, возможно, было результатом того, как был сформулирован мой ответ. Чтобы использовать ваш пример, это будет похоже на «var foo = 2, bar = foo ++;' Теперь 'bar === 3' и' foo === 3' – Adam

+0

О, интересно. Я не понимал, что подобные методы будут мутировать исходный var в памяти. Я думал, что они повлияли только на заимствованную ссылку, используемую в новом определении. Хорошо иметь в виду. Благодаря! –

0

Реальное эффективное решение заключается в использовании красного и черного двоичного дерева (http://en.wikipedia.org/wiki/Red%E2%80%93black_tree), где вы будете хранить в каждом узле одно значение массива, дельта с предыдущим и следующим элементом, а также относительное положение до медиана. Затем, только с небольшим обходом, вы должны иметь возможность идентифицировать последний элемент (последний элемент - тот, у которого индекс с наибольшим разбросом по медианному индексу, с предыдущим элементом и без следующего элемента).

Фокус в том, что каждый обход принимает только O (ln (n)), и поскольку вы выполняете меньше, чем ln (n) обход, время ниже O (sq (ln (n))), так что это очень быстро.

Редактировать: после конструктивных комментариев Bergi я просто задаюсь вопросом, не будет ли быстрее использовать массивы для этого, используя быстрое преобразование Фурье в массиве, содержащем все индексы массива, а затем идентифицирует последний элемент с затем преобразуйте назад массив, чтобы получить номер из частоты. Я прошу прощения, если я неясен, я не вижу четко всех шагов на момент написания, но я думаю, что это стоит того.

+2

Мы можем предположить, что массивы (и векторы) имеют известную длину и постоянное время поиска, поэтому это намного лучше, чем большинство реализаций дерева :-) – Bergi

+0

@Bergi: спасибо, тогда мне придется копаться в спецификациях javascript. я редактировал. – GameAlchemist

+1

Ну, похоже, вы неправильно поняли вопрос. OP просто хочет получить доступ к «последнему» элементу в массиве, а не к самому большому или что-то еще. – Bergi

Смежные вопросы