Получить последний элемент в массиве


1142

Вот мой код JavaScript:

var linkElement = document.getElementById("BackButton");
var loc_array = document.location.href.split('/');
var newT = document.createTextNode(unescape(capWords(loc_array[loc_array.length-2]))); 
linkElement.appendChild(newT);

В настоящее время он занимает от второго до последнего элемента в массиве из URL. Тем не менее, я хочу сделать проверку последнего элемента в массиве "index.html"и, если это так, вместо этого взять третий элемент до последнего.

Ответы:


1227
if (loc_array[loc_array.length - 1] === 'index.html') {
   // do something
} else {
   // something else
}

В случае, если ваш сервер обслуживает один и тот же файл «index.html» и «index.html» вы также можете использовать: .toLowerCase().

Тем не менее, вы можете рассмотреть возможность использования этой серверной части, если это возможно: она будет чище и будет работать для людей без JS.


если вам просто нужен последний элемент, вы можете Array.pop ()
Бадри Дерахшан

1052

Не уверен, что есть недостаток, но это кажется довольно лаконичным:

arr.slice(-1)[0] 

или

arr.slice(-1).pop()

Оба вернутся, undefinedесли массив пуст.


32
использовать деструктуризацию тоже приятно:const [lastItem] = arr.slice(-1)
диачелик

@diachedelic это самый приятный способ! Потрясающие!
Труфа

2
.pop()удаляет последний элемент, который изменяет исходный массив. Это не то же самое, что просто получить это значение.
Badrush

4
@Badrush slice () создает новый массив с копией одного элемента, а pop изменяет только эту копию. исходный массив остается целым
kritzikratzi

Но вы должны избегать создания новых массивов, если этот код не вызывается часто. В противном случае это создаст дополнительную нагрузку на сборщик мусора и / или заставит браузер использовать больше памяти.
mvmn

259

Используйте Array.pop :

var lastItem = anArray.pop();

Важно : это возвращает последний элемент и удаляет его из массива


165

Более короткая версия того, что написал @chaiguy:

Array.prototype.last = function() {
    return this[this.length - 1];
}

Чтение индекса -1 undefinedуже возвращает .

РЕДАКТИРОВАТЬ:

В наши дни предпочтение отдается использованию модулей, чтобы не касаться прототипа и не использовать глобальное пространство имен.

export function last(array) {
    return array[array.length - 1];
}

8
Если это не так очевидно , как это должно быть на самом деле используется, вот пример: var lastItem = [3,2,1,5].last();. Значение lastItemэто 5.
user128216

7
Этот ответ правильный и также довольно чистый, НО (!!!) Эмпирическое правило, использующее Javascript, таково Do NOT modify objects you Do NOT own. Это опасно по многим причинам, таким как 1. Другие разработчики, работающие в вашей команде, могут запутаться, поскольку этот метод не является стандартным 2. При любом обновлении в библиотеках или даже при использовании более низкой или более высокой версии ECMAScript его легко можно потерять!
Farzad YZ

1
Для всех, кто интересуется, это нарушает Array.forEach (). Я по-прежнему согласен с тем, что модификация прототипов - это не самое плохое, но это плохо.
Сеф Рид

1
По-моему, с модификациями проблем не так много Array.prototype, но вы должны их использовать Object.assign(Array.prototype, 'last', { value: function () { … } });. В противном случае свойство будет перечисляемым.
黄雨伞


70

Вот как получить его без эффекта на оригинальном массиве

a = [1,2,5,6,1,874,98,"abc"];
a.length; //returns 8 elements

Если вы используете pop (), он изменит ваш массив

a.pop();  // will return "abc" AND REMOVES IT from the array 
a.length; // returns 7

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

a.slice(-1).pop(); // will return "abc" won't do modify the array 
                   // because slice creates a new array object 
a.length;          // returns 8; no modification and you've got you last element 

6
Вы должны сделать slice (-1) .pop (), иначе вы скопируете весь массив (вам действительно нужно скопировать только последний элемент).
kritzikratzi

pop()Тогда в этом нет необходимости : просто сделайтеarr.slice(-1)[0]
Кристоф Маруа

56

Самый «чистый» путь ES6 (IMO) будет:

const foo = [1,2,3,4];
const bar = [...foo].pop();

Это позволяет избежать мутаций foo, как .pop()если бы мы не использовали оператор распространения.
Тем не менее, мне нравится, а также foo.slice(-1)[0]решение.


1
Вы также можете использовать деструктуризацию массива, чтобы сделать его более ES6;) stackoverflow.com/a/46485581/31671
alex

36
Обратите внимание, что это решение выполняет копирование всего массива.
Брендан Аннебл

4
Это так же нечитаемо, как .slice(-1)[0]и медленнее. .slice
Можно

12
Копирование всего массива только для «чистого» синтаксиса кажется мне глупым. Это даже не выглядит так хорошо
Джемар Джонс

43

Я бы лучше использовал, array.pop()чем индексы.

while(loc_array.pop()!= "index.html"){
}
var newT = document.createTextNode(unescape(capWords(loc_array[loc_array.length])));

таким образом, вы всегда получаете элемент, предшествующий index.html (при условии, что ваш массив содержит изолированный index.html как один элемент). Примечание: вы потеряете последние элементы из массива.


38

Я думаю, если вы хотите получить элемент без удаления, проще использовать это:

arr.slice(-1)[0]

Примечание. Если массив пуст (например, []), он вернетсяundefined .

кстати ... я не проверял производительность, но я думаю, что проще написать и написать


Обратите внимание, что a) это возвращает не последнее значение, а массив с последним элементом ( arr.slice(-1)[0] === arr[arr.length - 1]), и b) оно медленное, потому что копирует arrв новый массив (см. Stackoverflow.com/a/51763533/2733244 для измерения производительности).
Ворсварт

33

const [lastItem] = array.slice(-1);

Array.prototype.slice с -1 можно использовать для создания нового массива, содержащего только последний элемент исходного массива, затем вы можете использовать Destructuring Assignment для создания переменной с использованием первого элемента этого нового массива.

const lotteryNumbers = [12, 16, 4, 33, 41, 22];
const [lastNumber] = lotteryNumbers.slice(-1);

console.log(lotteryNumbers.slice(-1));
// => [22]
console.log(lastNumber);
// => 22


30

Получить последний элемент массива можно с помощью среза метода с отрицательными значениями.

Вы можете прочитать больше об этом здесь внизу.

var fileName = loc_array.slice(-1)[0];
if(fileName.toLowerCase() == "index.html")
{
  //your code...
}

Использование pop () изменит ваш массив, что не всегда является хорошей идеей.


1
Slice возвращает массив, так что используйте arr.slice(-1)[0], как этот ответ .
Сис Тиммерман

4
Если производительность является проблемой, знайте, что этот метод намного медленнее, чем array[array.length - 1] jsperf.com/get-last-item-from-array/13
Бруно Перес

29

Вы можете использовать этот шаблон ...

let [last] = arr.slice(-1);

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


25

Этот вопрос уже давно существует, поэтому я удивлен, что никто не упомянул о том, чтобы просто поставить последний элемент после a pop().

arr.pop()так же эффективен, как arr[arr.length-1], и оба имеют ту же скорость, что иarr.push() .

Таким образом, вы можете сойти с рук:

--- отредактировано [проверьте, что thePopне undefinedдо нажатия] ---

let thePop = arr.pop()
thePop && arr.push(thePop)

--- КОНЕЦ РЕДАКТИРОВАНИЯ ---

Который может быть уменьшен до этого (та же скорость [РЕДАКТИРОВАТЬ: но небезопасно!]):

arr.push(thePop = arr.pop())    //Unsafe if arr empty

Это в два раза медленнее arr[arr.length-1], но вам не нужно разбираться с индексом. Это стоит золота в любой день.

Из решений, которые я пробовал, и кратных единице времени выполнения (ETU) arr[arr.length-1]:

[Метод] .............. [ETUs 5 elems] ... [ETUs 1 миллион elems]

arr[arr.length - 1]      ------> 1              -----> 1

let myPop = arr.pop()
arr.push(myPop)          ------> 2              -----> 2

arr.slice(-1).pop()      ------> 36             -----> 924  

arr.slice(-1)[0]         ------> 36             -----> 924  

[...arr].pop()           ------> 120            -----> ~21,000,000 :)

Последние три варианта, ОСОБЕННО [...arr].pop(), становятся ОЧЕНЬ намного хуже, когда увеличивается размер массива. На машине без ограничений памяти моей машины, [...arr].pop()вероятно, поддерживается что-то вроде соотношения 120: 1. Тем не менее, никто не любит ресурсного борова.


3
Если исходный массив может быть пустым, этот подход приведет к неправильным результатам и []будет преобразован в [undefined]. Вам нужно защитить обратный толчок с помощью явной undefinedпроверки, что-то вродеmyPop !== undefined && arr.push(myPop)
dhilt

23

Если кто-то хочет получить последний элемент за один раз, он / она может использовать Array#splice():

lastElement = document.location.href.split('/').splice(-1,1);

Здесь нет необходимости хранить разделенные элементы в массиве, а затем переходить к последнему элементу. Если получение последнего элемента является единственной целью, это следует использовать.

Примечание: это изменяет исходный массив , удаляя его последний элемент. Думайте splice(-1,1)как pop()функция, которая выскакивает последний элемент.


5
Разве это не возвращает последний элемент в массиве вместо самого последнего элемента?

2
@tozazaburo не то же самое?
Арам Кочарян

5
это изменяет массив. Вы можете использовать slice (-1) вместо splice (-1), чтобы оставить исходный массив без изменений. @AramKocharyan нет его нет, сравнить ["hi"]против "hi".
kritzikratzi

20

Для тех, кто не боится перегружать прототип Array (и с маскировкой перечисления вам не следует):

Object.defineProperty( Array.prototype, "getLast", {
    enumerable: false,
    configurable: false,
    writable: false,
    value: function() {
        return this[ this.length - 1 ];
    }
} );


18

Я вообще использую underscorejs , с этим можно просто сделать

if (_.last(loc_array) === 'index.html'){
  etc...
}

Для меня это более семантически, чем loc_array.slice(-1)[0]


18

Вот еще искусство Javascript, если вы пришли сюда в поисках

В духе другого ответа, который использовал reduceRight(), но короче:

[3, 2, 1, 5].reduceRight(a => a);

Он основан на том факте, что, если вы не предоставите начальное значение, самый последний элемент будет выбран в качестве исходного (см. Документацию здесь ). Поскольку обратный вызов просто продолжает возвращать начальное значение, последний элемент будет тем, который возвращается в конце.

Помните, что это следует рассматривать как искусство Javascript, и я ни в коем случае не рекомендую делать это, в основном потому, что он выполняется за время O (n), а также потому, что это ухудшает читабельность.

А теперь серьезный ответ

Лучший способ, который я вижу (учитывая, что вы хотите его более кратким, чем array[array.length - 1]), заключается в следующем:

const last = a => a[a.length - 1];

Тогда просто используйте функцию:

last([3, 2, 1, 5])

Функция на самом деле полезна в случае, если вы имеете дело с анонимным массивом, подобным [3, 2, 1, 5]используемому выше, в противном случае вам придется создавать его дважды, что было бы неэффективно и уродливо:

[3, 2, 1, 5][[3, 2, 1, 5].length - 1]

Тьфу.

Например, вот ситуация, когда у вас есть анонимный массив и вам нужно определить переменную, но вы можете использовать last()вместо этого:

last("1.2.3".split("."));

16

Просто поставлю еще один вариант здесь.

loc_array.splice(-1)[0] === 'index.html'

Я нашел вышеупомянутый подход более чистым и коротким. Пожалуйста, не стесняйтесь попробовать это.

Примечание: он изменит исходный массив, если вы не хотите изменять его, вы можете использовать slice()

loc_array.slice(-1)[0] === 'index.html'

Спасибо @VinayPai за указание на это.


Согласно комментарию stackoverflow.com/users/510036/qix-monica-was-mistreated к этому сообщению stackoverflow.com/questions/9050345/… и тестам на jsperf.com/last-array-element2, которые очень медленные
Субаш

13

Несколько способов найти последнее значение массива в JavaScript

  • Без влияния на исходный массив

var arr = [1,2,3,4,5];

console.log(arr.slice(-1)[0])
console.log(arr[arr.length-1])
const [last] = [...arr].reverse();
console.log(last)
console.log(arr.reverse()[0])

  • Изменяет исходный массив

var arr = [1,2,3,4,5];

console.log(arr.pop())
arr.push(5)
console.log(...arr.splice(-1));

  • Создав собственный вспомогательный метод

let arr = [1, 2, 3, 4, 5];

Object.defineProperty(arr, 'last', 
{ get: function(){
  return this[this.length-1];
 }
})

console.log(arr.last);


Если ваш первый пример, где вы заявляете «Не затрагивая исходный массив» и поступая так, как предлагалось: console.log(arr.reverse()[0]) - Поздравляем, вы только что изменили исходный массив.
Роко Бульян


10

Лично я бы приветствовал ответ от kuporific / kritzikratzi. Метод array [array.length-1] становится очень уродливым, если вы работаете с вложенными массивами.

var array = [[1,2,3], [4,5,6], [7,8,9]]

array.slice(-1)[0]

//instead of 

array[array.length-1]

//Much easier to read with nested arrays

array.slice(-1)[0].slice(-1)[0]

//instead of

array[array.length-1][array[array.length-1].length-1]

10

В стадии предложения ECMAScript 1 предлагается добавить свойство массива, которое будет возвращать последний элемент: offer-array-last .

Синтаксис:

arr.lastItem // get last item
arr.lastItem = 'value' // set last item

arr.lastIndex // get last index

Вы можете использовать полифилл .

Автор предложения: Кит Циркель ( Chai Autor)


10

Для предотвращения удаления последнего элемента из исходного массива вы можете использовать

Array.from(myArray).pop()

В основном поддерживается всеми браузерами (ES6)


1
удачи с большими массивами из 100.000 элементов и более.
Солдеплата Сакетос

9

Вы можете добавить last()функцию к Arrayпрототипу.

Array.prototype.last = function () {
    return this[this.length - 1];
};

9

Все, что вы делаете, не просто использоватьreverse() !!!

В нескольких ответах упоминается, reverseно не упоминается тот факт, что он reverseизменяет исходный массив и не (как в некоторых других языках или платформах) не возвращает копию.

var animals = ['dog', 'cat'];

animals.reverse()[0]
"cat"

animals.reverse()[0]
"dog"

animals.reverse()[1]
"dog"

animals.reverse()[1]
"cat"

Это может быть худший тип кода для отладки!


4
Если вам нужна обратная копия вашего массива, вы можете использовать оператор распространения сейчас. Например[...animals].reverse()
Джош Р

Вы можете просто скопировать массив, прежде чем использовать реверс[1,3,4,5,"last"].slice().reverse()[0]
Madeo

9

Уничтожение объектов ES6 - это еще один путь.

const {length, [length-1]: last}=[1,2,3,4,5]
console.log(last)

Вы извлекаете свойство длины из массива, используя деструктуризацию объекта. Вы создаете другой динамический ключ, используя уже извлеченный ключ с помощью [length-1], и назначаете его последнему , все в одной строке.


немного сложно, но умно.
Адриен Кастальола

Спасибо, можете ли вы объяснить, что именно это делает?
Тарун Нагпал

8

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

Получатели позволяют получить доступ к возвращаемому значению функции так же, как если бы это было значение свойства. Возвращаемое значение функции, конечно, является последним значением массива (this[this.length - 1] ).

Наконец, вы заключаете его в условие, которое проверяет, lastявляется ли свойство -pro все еще undefined(не определено другим сценарием, который может полагаться на него).

if(typeof Array.prototype.last === 'undefined') {
    Object.defineProperty(Array.prototype, 'last', {
        get : function() {
            return this[this.length - 1];
        }
    });
}

// Now you can access it like
[1, 2, 3].last;            // => 3
// or
var test = [50, 1000];
alert(test.last);          // Says '1000'

Не работает в IE ≤ 8.


Array.prototype.lastэто всегда undefined? If не работает под Chrome 36
bryc

7

Отредактированный:

Недавно я придумал еще одно решение, которое сейчас мне кажется наилучшим для моих нужд:

function w(anArray) {
  return {
    last() {
      return anArray [anArray.length - 1];
    };
  };
}

С учетом приведенного выше определения я могу теперь сказать:

let last = w ([1,2,3]).last();
console.log(last) ; // -> 3

Название "W" означает «обертка». Вы можете увидеть, как вы можете легко добавить больше методов, кроме 'last ()' к этой оболочке.

Я говорю «лучше всего для моих нужд», потому что это позволяет мне легко добавлять другие такие «вспомогательные методы» к любому встроенному типу JavaScript. Например, на ум приходят car () и cdr () из Lisp.


Зачем использовать обертку? Если вам нужно вызвать wфункцию, просто заставьте функцию вернуть последний элемент.
Фреганте

w([1,2,3]).lengthне определено w([1,2,3])[1]не определено Не похоже на обертку для меня. И есть синтаксическая ошибка. У вас есть дополнительный ';'. См. Stackoverflow.com/a/49725374/458321 о том, как написать оболочку класса (класс SutString) и использовать отражение для заполнения этой оболочки. Хотя, имхо, фантики излишни. Лучше использовать инкапсуляцию, как у вас почти есть. return { arr: anArray, last() { return anArray[anArray.length - 1]; } };, Кроме того, w слишком общий. Вызов ArrayW или что-то.
TamusJRoyce

6

Я думаю, что самый простой и супер неэффективный способ:

var array = ['fenerbahce','arsenal','milan'];
var reversed_array = array.reverse(); //inverts array [milan,arsenal,fenerbahce]
console.log(reversed_array[0]) // result is "milan".

43
Это решение занимает O (n) больше памяти и занимает O (n) время. Это действительно не идеальное решение.
hlin117
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.