Zdobądź ostatni element w tablicy

1142

Oto mój kod JavaScript do tej pory:

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);

Obecnie trwa od drugiego do ostatniego elementu w tablicy z adresu URL. Chcę jednak sprawdzić, czy ma być ostatni element w tablicy, "index.html"a jeśli tak, to zamiast tego złap trzeci.

balexander
źródło

Odpowiedzi:

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

W przypadku, gdy serwer służy do tego samego pliku na „index.html” i „index.html” można również użyć: .toLowerCase().

Chociaż możesz rozważyć zrobienie tego po stronie serwera, jeśli to możliwe: będzie czystsze i będzie działać dla osób bez JS.

Aaron Harun
źródło
1050

Nie jestem pewien, czy istnieje wada, ale wydaje się to dość zwięzłe:

arr.slice(-1)[0] 

lub

arr.slice(-1).pop()

Oba powrócą, undefinedjeśli tablica jest pusta.

kritzikratzi
źródło
31
fajne jest też użycie destrukcji:const [lastItem] = arr.slice(-1)
diachedelic
@diachedelic to najsprytniejszy sposób! Niesamowite!
Trufa
1
.pop()usuwa ostatni element, który modyfikuje oryginalną tablicę. To nie to samo, co zwykłe wyszukiwanie tej wartości.
Badrush
3
@Badrush slice () tworzy nową tablicę z kopią jednego elementu, a pop modyfikuje tylko tę kopię. pierwotna tablica pozostaje nienaruszona
kritzikratzi
Należy jednak unikać tworzenia nowych tablic, chyba że ten kod nie jest często wywoływany. W przeciwnym razie spowoduje to dodatkowe obciążenie w zakresie wyrzucania elementów bezużytecznych i / lub zwiększy wykorzystanie pamięci przez przeglądarkę.
mvmn
259

Użyj Array.pop :

var lastItem = anArray.pop();

Ważne : Zwraca ostatni element i usuwa go z tablicy

mohawke
źródło
165

Krótsza wersja tego, co opublikował @chaiguy:

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

Odczytywanie indeksu -1 undefinedjuż powraca .

EDYTOWAĆ:

Obecnie preferuje się używanie modułów i unikanie dotykania prototypu lub korzystania z globalnej przestrzeni nazw.

export function last(array) {
    return array[array.length - 1];
}
Aram Kocharyan
źródło
8
Jeśli nie jest to oczywiste, jak to ma być rzeczywiście używany, oto przykład: var lastItem = [3,2,1,5].last();. Wartość lastItemwynosi 5.
user128216,
7
Ta odpowiedź jest poprawna, a także całkiem czysta, ALE (!!!) Podstawową zasadą jest używanie Javascript Do NOT modify objects you Do NOT own. Jest to niebezpieczne z wielu powodów, takich jak: 1. Inni programiści pracujący w twoim zespole mogą się pomylić, ponieważ ta metoda nie jest standardowa 2. przy każdej aktualizacji bibliotek lub nawet przy użyciu niższej lub wyższej wersji ECMAScript może łatwo UTRACIĆ!
Farzad YZ
1
Dla każdego, kto się zastanawia, powoduje to uszkodzenie Array.forEach (). Nadal zgadzam się, że modyfikowanie prototypów nie jest najgorszą rzeczą, ale ta jest zła.
Seph Reed
1
Imo nie ma tak dużego problemu z modyfikacją Array.prototype, ale powinieneś użyć Object.assign(Array.prototype, 'last', { value: function () { … } });. W przeciwnym razie właściwość będzie policzalna.
黄 雨伞
70

Oto, jak go uzyskać bez wpływu na oryginalną tablicę

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

Jeśli użyjesz pop (), zmodyfikuje twoją tablicę

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

Ale możesz użyć tego, aby nie miało to wpływu na oryginalną tablicę:

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
źródło
6
powinieneś zrobić slice (-1) .pop (), w przeciwnym razie skopiujesz całą tablicę (tak naprawdę wystarczy skopiować ostatni element).
kritzikratzi
Nie ma takiej potrzeby pop(): po prostu zróbarr.slice(-1)[0]
Christophe Marois,
56

„Najczystszym” sposobem ES6 (IMO) byłoby:

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

Pozwala to uniknąć mutacji foo, tak jak .pop()by to było, gdybyśmy nie korzystali z operatora rozprzestrzeniania.
To powiedziawszy, podoba mi się również foo.slice(-1)[0]rozwiązanie.

ddd
źródło
1
Możesz także użyć restrukturyzacji tablicy, aby uczynić ją bardziej ES6;) stackoverflow.com/a/46485581/31671
alex
36
Zauważ, że to rozwiązanie wykonuje kopię całej tablicy.
Brendan Annable,
4
Jest tak samo nieczytelny jak, .slice(-1)[0]ale wolniejszy. .slice
Równie
12
Kopiowanie całej tablicy tylko dla „czystej” składni wydaje mi się głupie. To nawet nie wygląda tak ładnie
Jemar Jones,
43

Wolałbym używać array.pop()niż indeksów.

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

w ten sposób zawsze otrzymujesz element poprzedzający index.html (pod warunkiem, że twoja tablica ma izolowany index.html jako jeden element). Uwaga: jednak stracisz ostatnie elementy z tablicy.

Pablo Mescher
źródło
38

Myślę, że jeśli chcesz tylko uzyskać element bez usuwania, to jest prostsze użyj tego:

arr.slice(-1)[0]

Uwaga: Jeśli tablica jest pusta (np. []), Funkcja zwróciundefined .

nawiasem mówiąc ... nie sprawdziłem wydajności, ale myślę, że jest prostszy i czystszy do napisania

terribleWeb
źródło
Zauważ, że a) to nie zwraca ostatniej wartości, ale tablica z ostatnim elementem ( arr.slice(-1)[0] === arr[arr.length - 1]), i b) jest powolna, ponieważ kopiuje arrsię do nowej tablicy (zobacz stackoverflow.com/a/51763533/2733244 w celu pomiaru wydajności).
wortwart
33

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

Array.prototype.slice z -1 można użyć do utworzenia nowej tablicy zawierającej tylko ostatni element oryginalnej tablicy, a następnie można użyć Przypisania do restrukturyzacji, aby utworzyć zmienną przy użyciu pierwszego elementu tej nowej tablicy.

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

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

Jamie Mason
źródło
30

Uzyskanie ostatniego elementu tablicy można osiągnąć za pomocą wycinka metody z wartościami ujemnymi.

Więcej na ten temat możesz przeczytać tutaj na dole.

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

Użycie pop () zmieni tablicę, co nie zawsze jest dobrym pomysłem.

Mohoch
źródło
1
Kawałek zwraca tablicę, choć, więc użytku arr.slice(-1)[0], jak tej odpowiedzi .
Cees Timmerman
4
Jeśli wydajność stanowi problem, wiedz, że ta metoda jest znacznie wolniejsza niż array[array.length - 1] jsperf.com/get-last-item-from-array/13
Bruno Peres
29

Możesz użyć tego wzoru ...

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

Choć brzmi to dość ładnie, należy pamiętać, że tworzy nową tablicę więc jest mniej wydajny niż inne rozwiązania, ale prawie nigdy nie będzie gardłem wydajności aplikacji.

alex
źródło
25

To pytanie było już dawno, więc jestem zaskoczony, że nikt nie wspomniał o ponownym włączeniu ostatniego elementu po pop() .

arr.pop()jest dokładnie tak samo wydajny, jak arr[arr.length-1]i oba mają taką samą prędkość jak arr.push().

Dlatego możesz uciec od:

--- EDYTOWANE [sprawdź, thePopczy nie jest undefinedprzed pchaniem] ---

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

--- EDYCJA KOŃCOWA ---

Co można zredukować do tej samej prędkości (ta sama prędkość [EDYCJA: ale niebezpieczne!]):

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

Jest to dwa razy wolniejsze niż arr[arr.length-1], ale nie musisz wypełniać indeksu. To jest warte złota każdego dnia.

Rozwiązań, które wypróbowałem oraz w wielokrotności jednostki czasu wykonania (ETU) arr[arr.length-1]:

[Metoda] .............. [ETU 5 elementów] ... [ETU 1 milion elementów]

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 :)

Ostatnie trzy opcje, W SZCZEGÓLNOŚCI [...arr].pop(), stają się BARDZO gorsze wraz ze wzrostem wielkości tablicy. Na komputerze bez ograniczeń pamięci mojego komputera [...arr].pop()prawdopodobnie zachowuje coś w rodzaju współczynnika 120: 1. Mimo to nikt nie lubi wieprza zasobów.

Paul Parker
źródło
3
Jeśli tablica początkowa może być pusta, to podejście będzie niepoprawne i []zostanie zmienione [undefined]. Musisz chronić pchnięcie do tyłu za pomocą jawnej undefinedkontroli, coś w stylumyPop !== undefined && arr.push(myPop)
dhilt
23

Jeśli ktoś chce uzyskać ostatni element za jednym razem, może użyć Array#splice():

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

W tym przypadku nie ma potrzeby przechowywania podzielonych elementów w tablicy, a następnie przejścia do ostatniego elementu. Jeśli zdobycie ostatniego elementu jest jedynym celem, należy to wykorzystać.

Uwaga: Zmienia to oryginalną tablicę poprzez usunięcie jej ostatniego elementu. Myśleć splice(-1,1)jako pop()funkcji, które pojawia ostatni element.

użytkownik1144616
źródło
5
Czy to nie zwraca ostatniego elementu w tablicy, zamiast samego ostatniego elementu?
2
@tozazaburo to nie to samo?
Aram Kocharyan
5
to modyfikuje tablicę. możesz użyć wycinka (-1) zamiast splajnu (-1), aby pozostawić oryginalną tablicę nietkniętą. @AramKocharyan No nie jego, porównaj ["hi"]vs "hi".
kritzikratzi
20

Dla tych, którzy nie boją się przeciążać prototypu Array (a przy maskowaniu wyliczeń nie powinieneś być):

Object.defineProperty( Array.prototype, "getLast", {
    enumerable: false,
    configurable: false,
    writable: false,
    value: function() {
        return this[ this.length - 1 ];
    }
} );
devios1
źródło
18

jQuery rozwiązuje to starannie:

> $([1,2,3]).get(-1)
3
> $([]).get(-1)
undefined
Cees Timmerman
źródło
18

Zazwyczaj używam podkreślników , dzięki którym możesz po prostu zrobić

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

Dla mnie jest to bardziej semantyczne niż loc_array.slice(-1)[0]

niels
źródło
18

Oto więcej sztuki Javascript, jeśli tu przyszedłeś jej szukać

W duchu innej odpowiedzi, która została użyta reduceRight(), ale krótsza:

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

Opiera się na fakcie, że jeśli nie podasz wartości początkowej, ostatni element jest wybierany jako element początkowy (sprawdź tutaj dokumenty ). Ponieważ wywołanie zwrotne po prostu zwraca wartość początkową, ostatni element będzie zwracany na końcu.

Uważaj, że należy to uznać za sztukę Javascript i nie jest to sposób, w jaki poleciłbym to zrobić, głównie dlatego, że działa w czasie O (n), ale także dlatego, że szkodzi czytelności.

A teraz poważna odpowiedź

Najlepszy sposób, jaki widzę (biorąc pod uwagę, że chcesz bardziej zwięzły niż array[array.length - 1]), to:

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

Następnie wystarczy użyć funkcji:

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

Ta funkcja jest przydatna w przypadku, gdy masz do czynienia z anonimową tablicą, taką jak [3, 2, 1, 5]używana powyżej, w przeciwnym razie musiałbyś utworzyć ją dwukrotnie, co byłoby nieefektywne i brzydkie:

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

Ugh.

Na przykład, oto sytuacja, w której masz anonimową tablicę i musisz zdefiniować zmienną, ale last()zamiast tego możesz użyć :

last("1.2.3".split("."));
Lucio Paiva
źródło
16

Po prostu umieszczam tutaj inną opcję.

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

Uważam, że powyższe podejście jest bardziej czyste i krótkie onliner. Proszę, spróbuj tego.

Uwaga: zmodyfikuje oryginalną tablicę, jeśli nie chcesz jej modyfikować, możesz jej użyć slice()

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

Dzięki @VinayPai za zwrócenie na to uwagi.

sidgujrathi
źródło
13

Wiele sposobów na znalezienie ostatniej wartości tablicy w javascript

  • Bez wpływu na oryginalną tablicę

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])

  • Modyfikuje oryginalną tablicę

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

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

  • Tworząc własną metodę pomocniczą

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

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

console.log(arr.last);

Vahid Akhtar
źródło
Jeśli twoim pierwszym przykładem jest „Bez wpływu na oryginalną tablicę” i postępując zgodnie z sugestią: console.log(arr.reverse()[0]) - gratulacje, właśnie zmodyfikowałeś oryginalną tablicę.
Roko C. Buljan
12
const lastElement = myArray[myArray.length - 1];

To najlepsze opcje z punktu widzenia wydajności (~ 1000 razy szybciej niż arr.slice (-1)).

Aleksander Burakowicz
źródło
10

Osobiście głosowałbym za odpowiedzią kuporific / kritzikratzi. Metoda array [array.length-1] staje się bardzo brzydka, jeśli pracujesz z zagnieżdżonymi tablicami.

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]
Michael Falck Wedelgård
źródło
10

Aby zapobiec usunięciu ostatniego elementu z tablicy pochodzenia, możesz użyć

Array.from(myArray).pop()

Obsługiwany głównie przez wszystkie przeglądarki (ES6)

Alexandr Malinin
źródło
1
powodzenia z dużymi tablicami zawierającymi 100 000 lub więcej elementów.
Soldeplata Saketos
9

Możesz dodać last()funkcję do Arrayprototypu.

Array.prototype.last = function () {
    return this[this.length - 1];
};
trinalbadger587
źródło
9

Cokolwiek robisz, nie tylko używajreverse() !!!

Kilka odpowiedzi wspomina, reverseale nie wspomina o tym, że reversemodyfikuje oryginalną tablicę i nie zwraca (jak w innym języku lub frameworku) kopii.

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

animals.reverse()[0]
"cat"

animals.reverse()[0]
"dog"

animals.reverse()[1]
"dog"

animals.reverse()[1]
"cat"

To może być najgorszy typ kodu do debugowania!

Simon_Weaver
źródło
4
Jeśli chcesz odwrócić kopię tablicy, możesz teraz użyć operatora rozkładania. np.[...animals].reverse()
Josh R
możesz po prostu skopiować tablicę przed użyciem wstecznej[1,3,4,5,"last"].slice().reverse()[0]
Madeo
9

Restrukturyzacja obiektów ES6 to kolejna droga.

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

Wyodrębniasz właściwość length z tablicy za pomocą destrukcji obiektu. Tworzysz kolejny klucz dynamiczny, używając już wyodrębnionego klucza przez [length-1] i przypisujesz go do końca , wszystko w jednym wierszu.

gautamits
źródło
trochę trudne, ale sprytne.
Adrien Castagliola
Dzięki, możesz wyjaśnić, co dokładnie robi?
Tarun Nagpal
8

Możesz dodać nowy getter właściwości do prototypuArray , aby był dostępny we wszystkich instancjachArray .

Gettery umożliwiają dostęp do wartości zwracanej przez funkcję tak, jakby to była wartość właściwości. Zwracana wartość funkcji jest oczywiście ostatnią wartością tablicy (this[this.length - 1] ).

Na koniec lastowijamy go w warunek, który sprawdza, czy właściwość -prop nadal jest undefined(nie zdefiniowana przez inny skrypt, który może na niej polegać).

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'

Nie działa w IE ≤ 8.

Matmarbon
źródło
Array.prototype.lastjest zawsze undefined? The if nie działa pod Chrome 36
bryc
7

EDYTOWANE:

Ostatnio wymyśliłem jeszcze jedno rozwiązanie, które moim zdaniem jest najlepsze dla moich potrzeb:

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

Dzięki powyższej definicji mogę teraz powiedzieć:

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

Nazwa „w” oznacza „opakowanie”. Możesz zobaczyć, jak możesz łatwo dodać do tego opakowania więcej metod niż „last ()”.

Mówię „najlepiej dla moich potrzeb”, ponieważ pozwala mi to łatwo dodawać inne takie „metody pomocnicze” do każdego wbudowanego typu JavaScript. Na myśl przychodzi na przykład car () i cdr () z Lisp.

Panu Logic
źródło
Dlaczego warto korzystać z owijarki? Jeśli musisz wywołać wfunkcję, po prostu spraw, aby funkcja zwróciła ostatni element.
fregante
w([1,2,3]).lengthjest niezdefiniowany. w([1,2,3])[1]jest niezdefiniowany. Nie wygląda mi to na opakowanie. I jest błąd składniowy. Masz dodatkowe „;”. Zobacz stackoverflow.com/a/49725374/458321, aby dowiedzieć się, jak napisać opakowanie klasy (klasa SutString) i użyć refleksji, aby wypełnić to opakowanie. Chociaż, imho, opakowania są przesadzone. Lepiej używać enkapsulacji, jak prawie masz. return { arr: anArray, last() { return anArray[anArray.length - 1]; } };. Ponadto w jest zbyt ogólne. Call to ArrayW lub coś takiego.
TamusJRoyce,
6

Myślę, że najłatwiejszym i najbardziej nieefektywnym sposobem jest:

var array = ['fenerbahce','arsenal','milan'];
var reversed_array = array.reverse(); //inverts array [milan,arsenal,fenerbahce]
console.log(reversed_array[0]) // result is "milan".
Osman Erdi
źródło
43
To rozwiązanie zajmuje O (n) więcej pamięci i zajmuje O (n) czas. To naprawdę nie jest idealne rozwiązanie.
hlin117,