Lấy mục cuối cùng trong một mảng


1142

Đây là mã JavaScript của tôi cho đến nay:

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

Hiện tại, nó mất mục thứ hai đến mục cuối cùng trong mảng từ URL. Tuy nhiên, tôi muốn kiểm tra mục cuối cùng trong mảng "index.html"và nếu có, hãy lấy mục thứ ba đến mục cuối cùng để thay thế.

Câu trả lời:


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

Trong trường hợp máy chủ của bạn phục vụ cùng một tệp cho "index.html" và "inDEX.htML", bạn cũng có thể sử dụng : .toLowerCase().

Mặc dù vậy, bạn có thể muốn xem xét thực hiện phía máy chủ này nếu có thể: nó sẽ sạch hơn và hoạt động cho những người không có JS.


1051

Không chắc chắn nếu có nhược điểm, nhưng điều này có vẻ khá súc tích:

arr.slice(-1)[0] 

hoặc là

arr.slice(-1).pop()

Cả hai sẽ trở lại undefinednếu mảng trống.


31
sử dụng phá hủy cũng tốt:const [lastItem] = arr.slice(-1)
diachedelic

@diachedelic đây là cách dễ nhất! Tuyệt vời!
Trufa

1
.pop()loại bỏ phần tử cuối cùng sửa đổi mảng ban đầu. Nó không giống như chỉ đơn giản là lấy ra giá trị đó.
Badrush

3
@Badrush lát () tạo mảng mới với một bản sao của một phần tử duy nhất và pop chỉ sửa đổi bản sao đó. mảng ban đầu vẫn không hề hấn gì
kritzikratzi

Nhưng bạn nên tránh tạo mảng mới trừ khi mã này không được gọi thường xuyên. Nếu không, nó sẽ gây thêm căng thẳng cho bộ sưu tập rác và / hoặc sẽ khiến trình duyệt sử dụng nhiều bộ nhớ hơn.
mvmn

259

Sử dụng Array.pop :

var lastItem = anArray.pop();

Quan trọng : Điều này trả về phần tử cuối cùng loại bỏ nó khỏi mảng


165

Phiên bản ngắn hơn của những gì @chaiguy đã đăng:

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

Đọc chỉ số -1 trả về undefinedrồi.

BIÊN TẬP:

Ngày nay, sở thích dường như đang sử dụng các mô-đun và để tránh chạm vào nguyên mẫu hoặc sử dụng không gian tên toàn cầu.

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

8
Nếu không rõ ràng cách sử dụng này thực sự được sử dụng, thì đây là một ví dụ : var lastItem = [3,2,1,5].last();. Giá trị của lastItem5.
dùng128216

7
Câu trả lời này là chính xác và cũng khá sạch sẽ NHƯNG (!!!) Một quy tắc sử dụng Javascript là vậy Do NOT modify objects you Do NOT own. Điều này nguy hiểm vì nhiều lý do, chẳng hạn như 1. Các nhà phát triển khác làm việc trong nhóm của bạn có thể bị nhầm lẫn vì phương pháp này không phải là tiêu chuẩn 2. với bất kỳ cập nhật nào trong thư viện hoặc thậm chí sử dụng phiên bản ECMAScript thấp hơn hoặc cao hơn, nó có thể dễ dàng bị LOST!
Farzad YZ

1
Đối với bất cứ ai tự hỏi, điều này phá vỡ Array.forEach (). Tôi vẫn đồng ý rằng sửa đổi nguyên mẫu không phải là điều tồi tệ nhất ngoài kia, nhưng cái này là xấu.
Seph Reed

1
Imo không có vấn đề lớn như vậy với việc sửa đổi Array.prototype, nhưng bạn nên sử dụng Object.assign(Array.prototype, 'last', { value: function () { … } });. Nếu không tài sản sẽ được vô số.


70

Đây là cách để có được nó mà không ảnh hưởng đến ARRAY ban đầu

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

Nếu bạn sử dụng pop (), nó sẽ sửa đổi mảng của bạn

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

Nhưng bạn có thể sử dụng điều này để nó không có hiệu lực trên mảng ban đầu:

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
bạn nên thực hiện lát (-1) .pop (), nếu không bạn sao chép toàn bộ mảng (bạn thực sự chỉ cần sao chép phần tử cuối cùng).
kritzikratzi

Không cần điều pop()đó sau đó: chỉ cần làmarr.slice(-1)[0]
Barshe Marois

56

Cách ES6 "sạch nhất" (IMO) sẽ là:

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

Điều này tránh đột biến foo, như .pop()đã có, nếu chúng ta không sử dụng toán tử lây lan.
Điều đó nói rằng, tôi thích foo.slice(-1)[0]giải pháp.


1
Bạn cũng có thể sử dụng tính năng phá hủy mảng để tạo thêm ES6;) stackoverflow.com/a/46485581/31671
alex

36
Lưu ý rằng giải pháp này thực hiện một bản sao của toàn bộ mảng.
Brendan Annable

4
Nó chỉ là không thể đọc được .slice(-1)[0]nhưng nó chậm hơn. Cũng có thể sử dụng.slice
fregante

12
Sao chép toàn bộ mảng chỉ với cú pháp "sạch" có vẻ ngớ ngẩn đối với tôi. Nó thậm chí trông không đẹp lắm
Jemar Jones

43

Tôi thích sử dụng array.pop()hơn chỉ mục.

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

bằng cách này, bạn luôn lấy phần tử trước cho index.html (cung cấp mảng của bạn đã tách index.html thành một mục). Lưu ý: Tuy nhiên, bạn sẽ mất các phần tử cuối cùng từ mảng.


38

Tôi nghĩ rằng nếu bạn chỉ muốn lấy phần tử mà không xóa, thì sử dụng đơn giản hơn:

arr.slice(-1)[0]

Lưu ý: Nếu mảng trống (ví dụ. []) Điều này sẽ trả về undefined.

Nhân tiện ... tôi đã không kiểm tra hiệu suất, nhưng tôi nghĩ đơn giản và gọn gàng hơn để viết


Lưu ý rằng a) điều này không trả về giá trị cuối cùng mà là một mảng có phần tử cuối cùng ( arr.slice(-1)[0] === arr[arr.length - 1]) và b) nó chậm vì nó sao chép arrvào một mảng mới (xem stackoverflow.com/a/51763533/2733244 để đo hiệu suất).
wortwart

33

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

Array.prototype.slice với -1 có thể được sử dụng để tạo Mảng mới chỉ chứa mục cuối cùng của Mảng gốc, sau đó bạn có thể sử dụng Phân định cấu trúc để tạo một biến bằng cách sử dụng mục đầu tiên của Mảng mới đó.

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

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


30

Lấy mục cuối cùng của một mảng có thể đạt được bằng cách sử dụng phương thức lát với các giá trị âm.

Bạn có thể đọc thêm về nó ở đây ở phía dưới.

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

Sử dụng pop () sẽ thay đổi mảng của bạn, điều này không phải lúc nào cũng là một ý tưởng tốt.


1
Slice trả về một mảng, mặc dù vậy, sử dụng arr.slice(-1)[0], như câu trả lời này .
Cees Timmerman

4
Nếu hiệu suất là một vấn đề, hãy biết rằng phương pháp này chậm hơn rất nhiều so với array[array.length - 1] jsperf.com/get-last-item-from-array/13
Bruno Peres

29

Bạn có thể sử dụng mẫu này ...

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

Trong khi nó đọc khá độc đáo, hãy ghi nhớ nó tạo ra một mảng mới vì vậy nó kém hiệu quả hơn so với các giải pháp khác nhưng nó sẽ gần như không bao giờ có các nút cổ chai hiệu suất của ứng dụng của bạn.


25

Câu hỏi này đã có từ rất lâu, vì vậy tôi rất ngạc nhiên khi không ai nhắc đến việc chỉ đưa yếu tố cuối cùng trở lại sau a pop().

arr.pop()chính xác là hiệu quả như arr[arr.length-1], và cả hai đều có cùng tốc độ arr.push().

Do đó, bạn có thể thoát khỏi:

--- EDITED [kiểm tra thePopkhông phải undefinedtrước khi đẩy] ---

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

--- KẾT THÚC ---

Có thể giảm xuống mức này (cùng tốc độ [EDIT: nhưng không an toàn!]):

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

Tốc độ này chậm gấp đôi arr[arr.length-1], nhưng bạn không phải loay hoay với một chỉ mục. Đó là giá trị vàng vào bất cứ ngày nào.

Trong số các giải pháp tôi đã thử và trong nhiều đơn vị Thời gian thực hiện (ETU) của arr[arr.length-1]:

[Phương pháp] .............. [ETU 5 elems] ... [ETU 1 triệu elem]

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

Ba tùy chọn cuối cùng, ĐẶC BIỆT [...arr].pop(), trở nên RẤT tệ hơn nhiều khi kích thước của mảng tăng lên. Trên một máy không có giới hạn bộ nhớ của máy tôi, [...arr].pop()có thể duy trì tỷ lệ 120: 1. Tuy nhiên, không ai thích một con heo tài nguyên.


3
Nếu mảng ban đầu có thể trống, cách tiếp cận này sẽ cho kết quả không chính xác và []sẽ được chuyển thành [undefined]. Bạn cần bảo vệ đẩy lùi bằng undefinedkiểm tra rõ ràng , đại loại nhưmyPop !== undefined && arr.push(myPop)
dhilt 6/2/19

23

Nếu một người muốn có được yếu tố cuối cùng trong một lần, anh ấy / cô ấy có thể sử dụng Array#splice():

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

Ở đây, không cần lưu trữ các phần tử phân tách trong một mảng, và sau đó đến phần tử cuối cùng. Nếu nhận được phần tử cuối cùng là mục tiêu duy nhất, thì điều này nên được sử dụng.

Lưu ý: Điều này thay đổi mảng ban đầu bằng cách loại bỏ phần tử cuối cùng của nó. Hãy nghĩ về splice(-1,1)như một pop()chức năng bật ra các yếu tố cuối cùng.


5
Điều này không trả về phần tử cuối cùng trong một mảng, thay vì chính phần tử cuối cùng phải không?

2
@tozazaburo không phải là điều tương tự?
Aram Kocharyan

5
Điều này sửa đổi mảng. bạn có thể sử dụng lát (-1) thay vì mối nối (-1) để giữ nguyên mảng ban đầu. @AramKocharyan không có, so sánh ["hi"]với "hi".
kritzikratzi

20

Đối với những người không ngại làm quá tải nguyên mẫu Array (và với mặt nạ liệt kê bạn không nên):

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


18

Tôi thường sử dụng dấu gạch dưới , với nó bạn chỉ có thể làm

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

Đối với tôi đó là nhiều ngữ nghĩa hơn loc_array.slice(-1)[0]


18

Đây là nghệ thuật Javascript nhiều hơn nếu bạn đến đây để tìm kiếm nó

Theo tinh thần của một câu trả lời khác được sử dụng reduceRight(), nhưng ngắn hơn:

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

Nó dựa vào thực tế là, trong trường hợp bạn không cung cấp giá trị ban đầu, phần tử cuối cùng được chọn làm giá trị ban đầu (kiểm tra tài liệu ở đây ). Vì cuộc gọi lại chỉ tiếp tục trả về giá trị ban đầu, nên phần tử cuối cùng sẽ là phần tử được trả về cuối cùng.

Coi chừng rằng điều này nên được coi là nghệ thuật Javascript và không có nghĩa là tôi sẽ khuyên bạn nên làm điều đó, chủ yếu là vì nó chạy trong thời gian O (n), nhưng cũng vì nó làm tổn thương khả năng đọc.

Và bây giờ cho câu trả lời nghiêm túc

Cách tốt nhất tôi thấy (xem xét bạn muốn nó ngắn gọn hơn array[array.length - 1]) là:

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

Sau đó, chỉ cần sử dụng chức năng:

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

Hàm này thực sự hữu ích trong trường hợp bạn đang xử lý một mảng ẩn danh như [3, 2, 1, 5]được sử dụng ở trên, nếu không, bạn phải khởi tạo nó hai lần, điều này sẽ không hiệu quả và xấu:

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

Ví dụ: đây là tình huống bạn có một mảng ẩn danh và bạn phải xác định một biến, nhưng bạn có thể sử dụng last()thay thế:

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

16

Chỉ cần đặt một lựa chọn khác ở đây.

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

Tôi tìm thấy cách tiếp cận trên sạch hơn và ngắn hơn. Xin vui lòng, cảm thấy miễn phí để thử cái này.

Lưu ý: Nó sẽ sửa đổi mảng ban đầu, nếu bạn không muốn sửa đổi nó, bạn có thể sử dụng slice()

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

Cảm ơn @VinayPai đã chỉ ra điều này.


Theo nhận xét của stackoverflow.com/users/510036/qix-monica-was-mistreated trên bài đăng này stackoverflow.com/questions/9050345/ và các bài kiểm tra tại jsperf.com/last-array-element2 rất chậm
Subash

13

Nhiều cách để tìm giá trị cuối cùng của một mảng trong javascript

  • Không ảnh hưởng đến mảng ban đầu

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

  • Sửa đổi mảng ban đầu

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

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

  • Bằng cách tạo phương thức trợ giúp riêng

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

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

console.log(arr.last);


Nếu ví dụ đầu tiên của bạn trong đó bạn nêu "Không ảnh hưởng đến mảng ban đầu" và bằng cách thực hiện như được đề xuất: console.log(arr.reverse()[0]) - xin chúc mừng, bạn chỉ cần sửa đổi mảng ban đầu.
Roko C. Buljan

12
const lastElement = myArray[myArray.length - 1];

Đây là các tùy chọn tốt nhất theo quan điểm hiệu suất (nhanh hơn 1000 lần so với Array.slice (-1)).


10

Cá nhân tôi sẽ nâng cao câu trả lời của kuporific / kritzikratzi. Phương thức mảng [Array.length-1] trở nên rất xấu nếu bạn làm việc với các mảng lồng nhau.

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

Để ngăn chặn mục cuối cùng khỏi mảng gốc, bạn có thể sử dụng

Array.from(myArray).pop()

Được hỗ trợ chủ yếu từ tất cả các trình duyệt (ES6)


1
chúc may mắn với mảng lớn từ 100.000 yếu tố trở lên.
Soldeplata Saketos

9

Bạn có thể thêm một last()chức năng cho Arraynguyên mẫu.

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

9

Dù bạn làm gì không chỉ sử dụng reverse()!!!

Một vài câu trả lời đề cập reversenhưng không đề cập đến thực tế reversesửa đổi mảng ban đầu và không (như trong một số ngôn ngữ hoặc khung khác) trả lại một bản sao.

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

animals.reverse()[0]
"cat"

animals.reverse()[0]
"dog"

animals.reverse()[1]
"dog"

animals.reverse()[1]
"cat"

Đây có thể là loại mã tồi tệ nhất để gỡ lỗi!


4
Nếu bạn muốn có một bản sao đảo ngược của mảng, bạn có thể sử dụng toán tử trải rộng ngay bây giờ. ví dụ như[...animals].reverse()
Josh R

bạn chỉ có thể sao chép mảng trước khi sử dụng ngược[1,3,4,5,"last"].slice().reverse()[0]
Madeo

9

Phá hủy đối tượng ES6 là một cách khác để đi.

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

Bạn trích xuất thuộc tính độ dài từ Array bằng cách sử dụng hủy đối tượng. Bạn tạo một khóa động khác bằng cách sử dụng khóa đã được trích xuất bằng [length-1] và gán nó cho cuối cùng , tất cả trong một dòng.


một chút khéo léo nhưng thông minh.
Adrien Castagliola

Cảm ơn, bạn có thể giải thích chính xác những gì nó làm?
Tarun Nagpal

8

Bạn có thể thêm một getter thuộc tính mới vào nguyên mẫuArray để nó có thể truy cập được thông qua tất cả các phiên bản củaArray .

Getters cho phép bạn truy cập giá trị trả về của hàm giống như giá trị của thuộc tính. Giá trị trả về của hàm tất nhiên là giá trị cuối cùng của mảng (this[this.length - 1] ).

Cuối cùng, bạn bọc nó trong một điều kiện để kiểm tra xem last-property có còn undefinedkhông (không được xác định bởi một tập lệnh khác có thể dựa vào nó).

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'

Không hoạt động trong IE 8.


Array.prototype.lastluôn là undefined? Nếu không hoạt động trong Chrome 36
bryc

7

EDITED:

Gần đây tôi đã đưa ra một giải pháp nữa mà bây giờ tôi nghĩ là tốt nhất cho nhu cầu của mình:

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

Với định nghĩa trên có hiệu lực bây giờ tôi có thể nói:

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

Tên "w" là viết tắt của "trình bao bọc". Bạn có thể thấy cách bạn có thể dễ dàng thêm nhiều phương thức hơn ngoài 'last ()' vào trình bao bọc này.

Tôi nói "tốt nhất cho nhu cầu của mình", vì điều này cho phép tôi dễ dàng thêm các "phương thức trợ giúp" khác vào bất kỳ loại tích hợp JavaScript nào. Điều gì đến với tâm trí là chiếc xe () và cdr () của Lisp chẳng hạn.


Tại sao nên sử dụng giấy gói? Nếu bạn phải gọi một whàm, chỉ cần làm cho hàm trả về mục cuối cùng.
fregante

w([1,2,3]).lengthkhông định nghĩa được. w([1,2,3])[1]không định nghĩa được. Có vẻ như không phải là một gói cho tôi. Và có một lỗi cú pháp. Bạn có thêm ';'. Xem stackoverflow.com/a/49725374/458321 để biết cách viết trình bao bọc lớp (lớp SutString) và sử dụng sự phản chiếu để điền vào trình bao bọc đó. Mặc dù, imho, giấy gói là quá mức cần thiết. Tốt hơn để sử dụng đóng gói, như bạn gần như có. return { arr: anArray, last() { return anArray[anArray.length - 1]; } };. Ngoài ra, w là cách quá chung chung. Gọi là ArrayW hoặc một cái gì đó.
TamusJRoyce

6

Tôi nghĩ cách dễ nhất và siêu kém hiệu quả là:

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

43
Giải pháp này cần thêm O (n) bộ nhớ và mất thời gian O (n). Đó thực sự không phải là giải pháp lý tưởng.
hlin117
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.