Отримайте останній елемент у масиві


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"і якщо так, то захопіть третій до останнього елемента.

Відповіді:


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

У разі, якщо ваш сервер обслуговує один і той же файл «index.html» і «index.html» ви також можете використовувати: .toLowerCase().

Хоча, можливо, ви захочете подумати, як це зробити на сервері, якщо це можливо: воно буде чистішим і працюватиме для людей без JS.


1051

Не впевнений, чи є недолік, але це здається досить стислим:

arr.slice(-1)[0] 

або

arr.slice(-1).pop()

Обидва повернуться, undefinedякщо масив буде порожнім.


31
використання руйнування також добре:const [lastItem] = arr.slice(-1)
діахеделік

@diachedelic - це найкрутіший спосіб! Дивовижно!
Труфа

1
.pop()видаляє останній елемент, який змінює вихідний масив. Це не те саме, що просто отримати це значення.
Бадруш

3
@Badrush slice () створює новий масив з копією одного елемента, а поп модифікує лише цю копію. оригінальний масив залишається неушкодженим
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. Інші розробники, які працюють у вашій команді, можуть заплутатися, оскільки цей метод не є стандартним. З будь-яким оновленням у бібліотеках або навіть з використанням нижчої або вищої версії ECMAScript він може легко втратити!
Farzad YZ

1
Для всіх, хто цікавиться, це порушує Array.forEach (). Я все ще погоджуюся, що модифікація прототипів - це не найгірше, але це погано.
Seph Reed

1
Imo, не існує такої великої проблеми з модифікацією Array.prototype, але ви повинні використовувати Object.assign(Array.prototype, 'last', { value: function () { … } });. Інакше майно буде численним.
黄 雨伞


70

Ось як це отримати, не впливаючи на оригінальний ARRAY

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
Алекс

36
Зауважте, що це рішення виконує копію всього масиву.
Брендан Аннабель

4
Це так само нечитабельно, як .slice(-1)[0]і повільніше. Можливо також використовувати.slice
fregante

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 .

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


Зауважте, що а) це не повертає останнє значення, а масив з останнім елементом ( arr.slice(-1)[0] === arr[arr.length - 1]), і b) він повільний, оскільки він копіює arrв новий масив (див. Stackoverflow.com/a/51763533/2733244 для вимірювання продуктивності).
wortwart

33

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

Array.prototype.slice з -1 може бути використаний для створення нового масиву, що містить лише останній елемент початкового масиву, потім можна використовувати призначення деструктуризації для створення змінної, використовуючи перший елемент цього нового масиву.

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], як ця відповідь .
Cees Timmerman

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)

--- END EDIT ---

Що можна зменшити до цього (однакова швидкість [EDIT: але небезпечна!]):

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

Це вдвічі повільніше arr[arr.length-1], але вам не доведеться заповнювати індекс. Це коштує золота в будь-який день.

З тих рішень, які я спробував, і в декількох одиницях часу виконання (ETU) arr[arr.length-1]:

[Метод] .............. [ETUs 5 elems] ... [ETU 1 мільйон елем]

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
це змінює масив. ви можете використати фрагмент (-1) замість сплайсу (-1), щоб залишити початковий масив недоторканим. @AramKocharyan немає його немає, порівняти ["hi"]проти "hi".
kritzikratzi

20

Для тих, хто не боїться перевантажувати прототип масиву (а з перерахунковим маскуванням вам не слід):

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


18

Я, як правило, використовую підкреслення , з цим ви просто можете зробити

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-mistreate на цій публікації 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.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

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

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()
Josh R

Ви можете просто скопіювати масив перед використанням зворотного[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.

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

Нарешті, ви загортаєте його в умову, що перевіряє, чи є last-власність все ще 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? Якщо не працює під 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. Що спадає на думку, це, наприклад, автомобіль () і cdr () Lisp.


Навіщо використовувати обгортку? Якщо вам потрібно викликати wфункцію, просто змусьте функцію повернути останній елемент.
fregante

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.