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

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

balexander
источник

Ответы:

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если массив пуст.

kritzikratzi
источник
32
использовать деструктуризацию тоже приятно:const [lastItem] = arr.slice(-1)
диачелик
@diachedelic это самый приятный способ! Потрясающие!
Труфа
2
.pop()удаляет последний элемент, который изменяет исходный массив. Это не то же самое, что просто получить это значение.
Badrush
4
@Badrush slice () создает новый массив с копией одного элемента, а pop изменяет только эту копию. исходный массив остается целым
kritzikratzi
Но вы должны избегать создания новых массивов, если этот код не вызывается часто. В противном случае это создаст дополнительную нагрузку на сборщик мусора и / или заставит браузер использовать больше памяти.
mvmn
259

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

var lastItem = anArray.pop();

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

Mohawke
источник
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 
ucefkh
источник
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 .

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

terribleWeb
источник
Обратите внимание, что 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 () изменит ваш массив, что не всегда является хорошей идеей.

Mohoch
источник
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()функция, которая выскакивает последний элемент.

user1144616
источник
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 ];
    }
} );
devios1
источник
18

JQuery решает это аккуратно:

> $([1,2,3]).get(-1)
3
> $([]).get(-1)
undefined
Сис Тиммерман
источник
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 за указание на это.

sidgujrathi
источник
Согласно комментарию 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]) - Поздравляем, вы только что изменили исходный массив.
Роко Бульян
12
const lastElement = myArray[myArray.length - 1];

Это лучший вариант с точки зрения производительности (~ в 1000 раз быстрее, чем arr.slice (-1)).

Александр Буракевич
источник
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];
};
trinalbadger587
источник
9

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

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

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

animals.reverse()[0]
"cat"

animals.reverse()[0]
"dog"

animals.reverse()[1]
"dog"

animals.reverse()[1]
"cat"

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

Simon_Weaver
источник
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], и назначаете его последнему , все в одной строке.

gautamits
источник
немного сложно, но умно.
Адриен Кастальола
Спасибо, можете ли вы объяснить, что именно это делает?
Тарун Нагпал
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.

Matmarbon
источник
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.

Panu Logic
источник
Зачем использовать обертку? Если вам нужно вызвать 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