获取数组中的最后一项


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"是否正确,如果是,请改为抓取倒数第三项。

Answers:


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

如果您的服务器为“ index.html”和“ inDEX.htML”提供相同的文件,则您也可以使用:.toLowerCase()

但是,如果可能的话,您可能要考虑在服务器端进行此操作:这将更干净并且可以在没有JS的情况下使用。


1048

不知道是否有缺点,但这似乎很简洁:

arr.slice(-1)[0] 

要么

arr.slice(-1).pop()

undefined如果数组为空,则两者都将返回。


31
使用解构也很好:const [lastItem] = arr.slice(-1)
diachedelic

@diachedelic这是最巧妙的方法!太棒了!
Trufa

1
.pop()删除最后一个修改原始数组的元素。这与简单地获取该值不同。
Badrush

2
@Badrush slice()使用单个元素的副本创建新数组,然后pop仅修改该副本。原始阵列未受到
破坏

但是您应该避免创建新的数组,除非不经常调用此代码。否则,它将对垃圾收集造成额外的压力,并且/或者将使浏览器使用更多的内存。
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();。值lastItemIS 5
user128216 2015年

7
这个答案是正确的,但也很干净BUT(!!!)使用Javascript的经验法则是that Do NOT modify objects you Do NOT own。由于许多原因,这很危险,例如1.团队中的其他开发人员可能会感到困惑,因为此方法不是标准的。2.在库中进行任何更新,甚至使用较低或较高版本的ECMAScript,都可能很容易丢失!
Farzad YZ

1
对于任何想知道的人,这都会破坏Array.forEach()。我仍然同意修改原型并不是最糟糕的事情,但这是不好的。
瑟夫·里德

1
Imo修改没有太大的问题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]
克里斯托夫Marois

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

顺便说一句...我没有检查性能,但我认为写起来更简单明了


请注意,a)不会返回最后一个值,而是返回带有最后一个元素(arr.slice(-1)[0] === arr[arr.length - 1])的数组,b)这样做很慢,因为它会复制arr到新数组中(有关性能评估,请参见stackoverflow.com/a/51763533/2733244)。
wortwart

33

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

带有-1的Array.prototype.slice可用于创建仅包含原始Array的最后一项的新Array,然后可以使用Destructuring Assignment使用该新Array的第一项来创建变量。

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

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


30

通过使用带负值的slice方法,可以获取数组的最后一项。

你可以阅读更多关于它在这里的底部。

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

使用pop()会更改数组,但这并不总是一个好主意。


1
不过,Slice会返回一个数组,因此请使用arr.slice(-1)[0],例如this answer
Cees Timmerman

4
如果性能是一个问题,请知道此方法比array[array.length - 1] jsperf.com/get-last-item-from-array/13
Bruno Peres

29

您可以使用此模式...

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

尽管它读起来很不错,但是请记住,它会创建一个新的数组,因此它的效率不如其他解决方案,但它几乎永远不会成为应用程序性能瓶颈。


25

这个问题已经存在了很长时间,所以令我惊讶的是,没有人提到只是将最后一个元素放到。之后pop()

arr.pop()与完全一样高效arr[arr.length-1],并且两者的速度相同arr.push()

因此,您可以摆脱:

---编辑[ 在推入之前thePop没有检查undefined] ---

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

---结束编辑-

可以降低到此速度(相同速度[EDIT:但不安全!]):

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

它的速度是的两倍arr[arr.length-1],但是您不必使用索引。在任何一天都值得黄金。

在我尝试过的解决方案中,以以下时间的执行时间单位(ETU)的倍数进行arr[arr.length-1]

[方法] .............. [ETUs 5个元素] ... [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是不是同一回事?
Aram Kocharyan

5
这将修改数组。您可以使用slice(-1)代替splice(-1)保持原始数组不变。它不是,比较@AramKocharyan没有["hi"]VS "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指出这一点。



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]) -恭喜,您刚刚修改了原始数组。
Roko C. Buljan


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

为了防止从原始数组中删除最后一项,您可以使用

Array.from(myArray).pop()

大多数浏览器(ES6)都受支持


1
拥有100.000个或更多元素的大型数组,祝您好运。
Soldeplata Saketos

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)

您可以使用对象解构从Array中提取length属性。您可以使用[length-1]提取的密钥来创建另一个动态密钥,并将其分配给last(全部在一行中)。


有点棘手,但很聪明。
艾德里安·卡斯塔廖拉

谢谢,您能解释一下它的确切作用吗?
塔伦·纳格帕

8

您可以在的原型中添加新的属性获取器Array以便可以通过的所有实例访问它Array

使用getter可以访问函数的返回值,就像它是属性的值一样。函数的返回值当然是数组的最后一个值(this[this.length - 1])。

最后,将其包装在一个条件下,该条件检查last-property是否仍然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 2014年

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内置类型中。例如,想到的是Lisp的car()和cdr()。


为什么要使用包装纸?如果必须调用一个w函数,只需使该函数返回最后一项即可。
fregante

w([1,2,3]).length未定义。w([1,2,3])[1]未定义。对我来说似乎不像是包装纸。并且存在语法错误。您还有一个额外的“;”。有关如何编写类包装器(SutString类)以及如何使用反射来填充该包装器的信息,请参见stackoverflow.com/a/49725374/458321。不过,恕我直言,包装器是过大的。更好地使用封装,就像您几乎拥有的一样。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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.