关于javascript:获取数组中的最后一项

Get the last item in an array

这是我目前为止的javascript代码:

1
2
3
4
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",如果是,则改为抓取第三个到最后一个项。


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

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

不过,如果可能的话,您可能会考虑使用服务器端:它将更干净,并且适用于没有JS的人。


不确定是否有缺点,但这看起来很简洁:

1
arr.slice(-1)[0]

1
arr.slice(-1).pop()

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


使用array.pop:

1
var lastItem = anArray.pop();

重要提示:这将返回最后一个元素并将其从数组中移除


@chaigoy发布的内容的较短版本:

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

读取-1索引将返回undefined

编辑:

如今,首选项似乎是使用模块,并避免接触原型或使用全局命名空间。

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


有两种选择:

1
var last = arr[arr.length - 1]

1
var last = arr.slice(-1)[0]

前者更快,但后者看起来更好

http://jspef.com/slice-vs-length-1-arr


以下是如何在不影响原始数组的情况下获得它

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

如果使用pop(),它将修改数组

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

但是您可以使用它,这样它就不会对原始数组产生影响:

1
2
3
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


"最干净"的ES6方式(IMO)是:

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

这就避免了foo的变异,就像.pop()如果我们不使用扩散操作符的话会发生的那样。也就是说,我也喜欢foo.slice(-1)[0]解决方案。


我宁愿使用array.pop()而不是索引。

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

这样,您总是可以得到index.html之前的元素(前提是您的数组将独立index.html作为一个项)。注意:不过,您将丢失数组中的最后一个元素。


使用带负值的切片方法可以得到数组的最后一项。

你可以在下面阅读更多关于它的信息。

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

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


我认为,如果您只想在不移除元素的情况下获取元素,那么更简单的做法是:

1
arr.slice(-1)[0]

注:如果数组为空(如[],则返回undefined

顺便说一句。。。我没有检查性能,但我认为写起来更简单更干净


你可以使用这个模式…

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

虽然它读起来相当好,但请记住,它创建了一个新的数组,因此比其他解决方案效率更低,但它几乎不会成为应用程序的性能瓶颈。


如果一个人想一次性获得最后一个元素,他/她可以使用Array#splice()

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

在这里,不需要将拆分的元素存储在数组中,然后到达最后一个元素。如果获取最后一个元素是唯一的目标,那么应该使用它。

注意:这将通过删除其最后一个元素来更改原始数组。把splice(-1,1)看作是弹出最后一个元素的pop()函数。


对于那些不怕重载数组原型的人(对于枚举屏蔽,您不应该这样做):

1
2
3
4
5
6
7
8
Object.defineProperty( Array.prototype,"getLast", {
    enumerable: false,
    configurable: false,
    writable: false,
    value: function() {
        return this[ this.length - 1 ];
    }
} );


我通常使用下划线,有了它,你就可以

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

对我来说,这比loc_array.slice(-1)[0]更语义化。


jquery巧妙地解决了这一问题:

1
2
3
4
> $([1,2,3]).get(-1)
3
> $([]).get(-1)
undefined


这个问题已经存在很长时间了,所以我很惊讶没有人提到仅仅在pop()之后重新启用最后一个元素。

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

因此,您可以摆脱:

---编辑[推前检查thePop不是undefined]---

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

---结束编辑---

可以降低到这个速度[编辑:但是不安全!))

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

这个速度是arr[arr.length-1]的两倍,但是你不必在索引上浪费时间。这在任何一天都是值得的。

我尝试过的解决方案,以及arr[arr.length-1]的执行时间单位(etu)的倍数:

[方法]……

1
2
3
4
5
6
7
8
9
10
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的比例。不过,没有人喜欢资源猪。


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

从性能角度来看,这是最佳选择(比arr.slice(-1)快约1000倍)。


就我个人而言,我会赞成Kuporific/Kritzikratzi的回答。如果使用嵌套数组,array[array.length-1]方法会变得非常难看。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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]


可以将last()函数添加到Array原型中。

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


编辑时间:

最近,我又提出了一个解决方案,我认为这是最适合我需要的:

1
2
3
4
5
6
7
function w(anArray) {
  return {
    last() {
      return anArray [anArray.length - 1];
    };
  };
}

根据上述定义,我现在可以说:

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

"w"代表"wrapper"。您可以看到如何轻松地添加更多除"last()"之外的方法。

我说"最适合我的需要",因为这允许我可以很容易地添加其他这样的"助手方法"任何javascript内置类型。什么来了请记住,lisp的car()和cdr()用于实例。


您可以在Array的原型中添加一个新的属性getter,以便可以通过Array的所有实例访问它。

getter允许您像访问属性值一样访问函数的返回值。函数的返回值当然是数组的最后一个值(this[this.length - 1])。

最后,在检查last属性是否仍然是undefined的条件下包装它(不由可能依赖它的另一个脚本定义)。

1
2
3
4
5
6
7
8
9
10
11
12
13
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。


这里有更多的javascript艺术如果你来这里找它

根据使用reduceRight()的另一个答案的精神,但更短:

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

它依赖于这样一个事实:如果您不提供初始值,则会选择最后一个元素作为初始元素(检查此处的文档)。由于回调只是不断返回初始值,最后一个元素将是最后一个返回的元素。

请注意,这应该被视为JavaScript艺术,决不是我推荐的方式,主要是因为它在O(n)时间内运行,但也因为它会损害可读性。

现在严肃的回答

我认为(考虑到你希望它比array[array.length - 1]更简洁)的最好方式是:

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

然后使用函数:

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

如果您处理上面使用的匿名数组(如[3, 2, 1, 5])时,该函数实际上很有用,否则您必须将其实例化两次,这将是低效和丑陋的:

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

呃。

例如,在这种情况下,您有一个匿名数组,需要定义一个变量,但是您可以使用last()

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

我认为最简单和超低效的方法是:

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


在ECMAScript Proposal Stage 1中,有一个建议添加一个数组属性,该属性将返回最后一个元素:Proposal Array Last。

语法:

1
2
3
4
arr.lastItem // get last item
arr.lastItem = 'value' // set last item

arr.lastIndex // get last index

您可以使用polyfill。

提案作者:Keith Cirkel(柴汽车)


我建议创建助手函数,并在每次使用它时都需要它。让函数更一般化,不仅可以得到最后一个项,还可以从最后一个项中获得第二个项等等。

1
2
3
4
function last(arr, i) {
    var i = i || 0;
    return arr[arr.length - (1 + i)];
}

用法很简单

1
2
3
4
var arr = [1,2,3,4,5];
last(arr);    //5
last(arr, 1); //4
last(arr, 9); //undefined

现在,让我们解决原始问题

Grab second to last item form array. If the last item in the loc_array is"index.html" grab the third to last item instead.

下一行做这项工作

1
last(loc_array, last(loc_array) === 'index.html' ? 2 : 1);

所以,你需要重写

1
var newT = document.createTextNode(unescape(capWords(loc_array[loc_array.length-2])));

以这种方式

1
var newT = document.createTextNode(unescape(capWords(last(loc_array, last(loc_array) === 'index.html' ? 2 : 1))));

或者使用附加变量来提高可读性

1
2
var nodeName = last(loc_array, last(loc_array) === 'index.html' ? 2 : 1);
var newT = document.createTextNode(unescape(capWords(nodeName)));


下面的情况如何?

1
2
3
4
5
if ('index.html' === array[array.length - 1]) {  
   //do this
} else {
   //do that
}

如果使用下划线或lodash,则可以使用_.last(),例如:

1
2
3
4
5
if ('index.html' === _.last(array)) {  
   //do this
} else {
   //do that
}

或者您可以创建自己的最后一个函数:

1
const _last = arr => arr[arr.length - 1];

使用方法如下:

1
2
3
4
5
if ('index.html' === _last(array)) {  
   //do this
} else {
   //do that
}


使用lodash_u.last(array)获取array的最后一个元素。

1
2
3
data = [1,2,3]
last = _.last(data)
console.log(last)

1
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js">


使用ES6/ES2015 Spread Operator(…)可以执行以下操作。

1
2
3
const data = [1, 2, 3, 4]
const [last] = [...data].reverse()
console.log(last)

请注意,使用spread operator和reverse并没有改变原始数组,这是获取数组最后一个元素的纯方法。


获取数组最后一项的简单方法:

1
var last_item = loc_array.reverse()[0];

当然,我们需要先检查以确保数组至少有一个项。


清洁高效:

1
2
3
let list = [ 'a', 'b', 'c' ]

(xs => xs[xs.length - 1])(list)

如果使用babel安装管道操作员,它将变为:

1
list |> (xs => xs[xs.length - 1])


另一个ES6唯一的选择是使用Array.find(item, index)=> {...})如下:

1
2
const arr = [1, 2, 3];
const last = arr.find((item, index) => index === arr.length - 1);

很少有实际价值,张贴显示索引也可用于您的过滤逻辑。


您也可以在不从URL提取数组的情况下实现此问题。

这是我的选择

1
var hasIndex = (document.location.href.search('index.html') === -1) ? doSomething() : doSomethingElse();

!问候语?


这可以通过lodash _.last_.nth来实现:

1
2
3
var data = [1, 2, 3, 4]
var last = _.nth(data, -1)
console.log(last)
1
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js">


这个方法不会干扰你的原型。它还可以防御0长度的阵列,以及null/undefined阵列。如果返回的默认值可能与数组中的项匹配,则甚至可以重写默认值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const items = [1,2,3]
const noItems = []

/**
 * Returns the last item in an array.
 * If the array is null, undefined, or empty, the default value is returned.
 */

function arrayLast (arrayOrNull, defVal = undefined) {
  if (!arrayOrNull || arrayOrNull.length === 0) {
    return defVal
  }
  return arrayOrNull[arrayOrNull.length - 1]
}

console.log(arrayLast(items))
console.log(arrayLast(noItems))
console.log(arrayLast(null))

console.log(arrayLast(items, 'someDefault'))
console.log(arrayLast(noItems, 'someDefault'))
console.log(arrayLast(null, 'someDefault'))


arrow函数通过不重复数组的名称,使执行速度最快的方法更加简洁。

1
var lastItem = (a => a[a.length - 1])(loc_array);


还有一个NPM模块,将last添加到Array.prototype中。

1
npm install array-prototype-last --save

使用

1
2
3
4
5
require('array-prototype-last');

[1, 2, 3].last; //=> 3

[].last; //=> undefined


无论你做什么,都不要使用reverse()!!!!

有几个答案提到了reverse,但没有提到reverse修改了原始数组,并且(在某些其他语言或框架中)没有返回副本。

1
2
3
4
5
6
7
8
9
10
11
12
13
var animals = ['dog', 'cat'];

animals.reverse()[0]
"cat"

animals.reverse()[0]
"dog"

animals.reverse()[1]
"dog"

animals.reverse()[1]
"cat"

这可能是要调试的最糟糕的代码类型!


要防止从源数组中删除最后一个项,可以使用

1
Array.from(myArray).pop()

主要支持所有浏览器(ES6)


使用还原光:

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


带-1的array.prototype.slice可用于创建仅包含原始数组最后一项的新数组,然后可以使用析构函数赋值创建使用新数组第一项的变量。

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

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


下面是一个干净的原型扩展,它可以简单地实现Aaron Harun的答案:

1
2
3
4
Array.prototype.i = function(val){
    if (val < 0) return this[this.length - Math.abs(val)]
    return this[val]
}

在定义了原型之后,这将起作用:

1
2
3
4
arr = [1, 2, 3, 4, 5]
arr.i(0)  // 1
arr.i(-1) // 5
arr.i(-2) // 4


这行吗?

1
2
3
4
5
6
if (loc_array.pop() =="index.html"){
var newT = document.createTextNode(unescape(capWords(loc_array[loc_array.length-3])));
}
else{
var newT = document.createTextNode(unescape(capWords(loc_array[loc_array.length-2])));
}


使用ramda进行功能编程

如果您使用的是JS,我建议您查看Ramda,它是一个功能性编程库(除了更高级和模块化的库外,还包括lodash和underline)。Ramda提供了R.Last。

1
2
3
4
5
6
import * as R from 'ramda';
R.last(['fi', 'fo', 'fum']); //=> 'fum'
R.last([]); //=> undefined

R.last('abc'); //=> 'c'
R.last(''); //=> ''

还提供了initheadtail。列出怪物(学习哈斯克尔)

List Monster