ChatGPT解决这个技术问题 Extra ChatGPT

获取数组中的最后一项

到目前为止,这是我的 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",如果是,则改为获取倒数第三项。


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

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

不过,如果可能的话,你可能会考虑在服务器端做这个:它会更干净,并且适合没有 JS 的人。

编辑-ES-2022

使用 ES-2022 Array.at(),上面的代码可以这样写:

if (loc_array.at(-1) === 'index.html') {
   // do something
} else {
   // something else
}

如果您只需要最后一项,您可以使用 Array.pop()
@BadriDerakhshan 这将不可避免地在返回数组之前从数组中删除最后一个元素,因此如果您只想检查数组的最后一个元素,这不是一个选项。您还必须将其推回以将阵列恢复到以前的状态。
@BadriDerakhshan 的解决方案对于创建的数组是临时的情况很有用。例如。而不是 x = string.split('/'); return x[x.length-1],你可以做 return x.split('/').pop()
在 Safari 上不起作用
Safari IOS、Chrome IOS 和 Samsung Internet 不支持 at() 方法caniuse.com/mdn-javascript_builtins_string_at
k
kuporific

不确定是否有缺点,但这似乎很简洁:

arr.slice(-1)[0] 

或者

arr.slice(-1).pop()

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


使用解构也很好:const [lastItem] = arr.slice(-1)
@Badrush slice() 使用单个元素的副本创建新数组,并且 pop 仅修改该副本。原始阵列完好无损
@mvmn 我很久以前做过一个基准测试,在单个 2.4ghz 线程上,吞吐量约为每秒一两百万次调用。因此,除非您解决了无论如何都不应该在 JS 中解决的问题,否则它不会引起注意(与 arr[arr.length-1] 相比,iirc 的减速是 50-100 倍)
这个方法很慢
@Govan 请看我的评论。您可以将其称为每秒过高的次数。如果您需要更多或准备好数组长度,请使用普通数组访问以获得最佳性能arr[arr.length-1]
S
Somatik

使用 Array.pop

var lastItem = anArray.pop();

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


特别适用于:filename.split('.').pop()
它不仅返回最后一个元素,而且将其删除!
const lastItem = [...anArray].pop() 将是避免突变的一种方法
A
Aram Kocharyan

@chaiguy 发布的内容的简短版本:

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

读取 -1 索引已经返回 undefined

编辑:

这些天来,偏好似乎是使用模块并避免接触原型或使用全局命名空间。

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

如果不清楚如何实际使用它,这里有一个示例:var lastItem = [3,2,1,5].last();lastItem 的值为 5
这个答案是正确的,也很干净但是(!!!)使用 Javascript 的经验法则是 Do NOT modify objects you Do NOT own。由于许多原因,它很危险,例如 1. 在您的团队中工作的其他开发人员可能会感到困惑,因为这种方法不是标准的 2. 库中的任何更新,甚至使用更低或更高的 ECMAScript 版本都可能很容易丢失!
对于任何想知道的人,这会破坏 Array.forEach()。我仍然同意修改原型并不是最糟糕的事情,但这个很糟糕。
我认为修改 Array.prototype 没有那么大的问题,但您应该使用 Object.assign(Array.prototype, 'last', { value: function () { … } });。否则,该属性将是可枚举的。
@FarzadYousefzadeh Interesting article 告诉何时以及如何修改 JS 原生原型。
J
Josh Click

两个选项是:

var last = arr[arr.length - 1]

或者

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

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

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


感谢您提供 jsperf 链接。从性能的角度来看,第二个选项是胡说八道。
第一个选项也很明显它的作用。第二个没那么多
C
Community

表现

今天 2020.05.16 我在 MacOs High Sierra v10.13.6 上在 Chrome v81.0、Safari v13.1 和 Firefox v76.0 上执行所选解决方案的测试

结论

arr[arr.length-1] (D) 被推荐为最快的跨浏览器解决方案

可变解决方案 arr.pop() (A) 和不可变 _.last(arr) (L) 很快

解决方案 I、J 对于长字符串来说很慢

解决方案 H、K (jQuery) 在所有浏览器上最慢

https://i.stack.imgur.com/smISX.png

细节

我测试了两种解决方案:

可变:A,B,C,

不可变:D、E、F、G、H、I、J(我的),

从外部库不可变:K、L、M、

两种情况

短字符串 - 10 个字符 - 你可以在这里运行测试

长字符串 - 1M 个字符 - 你可以在这里运行测试

函数 A(arr) { 返回 arr.pop(); } 函数 B(arr) { 返回 arr.splice(-1,1); } 函数 C(arr) { 返回 arr.reverse()[0] } 函数 D(arr) { 返回 arr[arr.length - 1]; } 函数 E(arr) { return arr.slice(-1)[0] ; } 函数 F(arr) { 让 [last] = arr.slice(-1);最后返回; } 函数 G(arr) { 返回 arr.slice(-1).pop(); } 函数 H(arr) { 返回 [...arr].pop(); } 函数 I(arr) { return arr.reduceRight(a => a); } function J(arr) { return arr.find((e,i,a)=> a.length==i+1); } 函数 K(arr) { 返回 $(arr).get(-1); } 函数 L(arr) { 返回 _.last(arr); } 函数 M(arr) { return _.nth(arr, -1); } // ---------- // 测试 // ---------- let loc_array=["domain","a","b","c","d ","e","f","g","h","file"]; log = (f)=> console.log(`${f.name}: ${f([...loc_array])}`); [A,B,C,D,E,F,G,H,I,J,K,L,M].forEach(f=> log(f));

短字符串的 Chrome 示例结果

https://i.stack.imgur.com/VYUMF.png


提到的数字是多少?越高越好吗?
即使您不必运行它们,我也可以猜到结果,哈哈。但我认为在这种情况下性能并不重要。
N
Neithan Max

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

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 

你应该做 slice(-1).pop(),否则你复制整个数组(你真的只需要复制最后一个元素)。
那么不需要那个pop():只需执行arr.slice(-1)[0]
R
Roko C. Buljan

“最干净”的 ES6 方式(IMO)将是:

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

如果我们不使用扩展运算符,这可以避免像 .pop() 那样改变 foo
也就是说,我也喜欢 foo.slice(-1)[0] 解决方案。


您还可以使用数组解构使其 more ES6 ;) stackoverflow.com/a/46485581/31671
请注意,此解决方案执行整个数组的副本。
它与 .slice(-1)[0] 一样不可读,但速度较慢。不妨使用 .slice
复制整个数组只是为了“干净”的语法对我来说似乎很愚蠢。它甚至看起来都不好看
J
Jamie Mason

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


in 2012 开始,已多次给出 .slice(-1) 答案,其含义已详细讨论(与此处不同)。请不要为了获得一些支持而给出重复的答案。
我最喜欢这个答案。我见过的其他 .slice(-1) 答案使用 [0] 而不是解构。 @diachedelic 的评论暗示了这种解构,但在我看来,它应该是一个答案而不是评论。很好的例子和链接也。
是的,其他答案不是同一个丹,你错过了对 slice(-1) 生成的数组中的解构赋值的使用。
k
kingbeencent
const [y] = x.slice(-1)

快速说明:这种语法 [y] = 被称为解构赋值,根据 Mozilla 文档,解构赋值可以将数组中的值或对象中的属性解包到不同的变量中阅读更多信息:这里


只使用 arr[arr.length - 1] 肯定更好,因为它在大多数浏览器上更具可读性和快一个数量级。
@acnebs 我同意,当你可以让它变得更容易时,为什么要让它变得更难。
a
alex

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

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

这样,您始终可以获取 index.html 之前的元素(前提是您的数组已将 index.html 隔离为一项)。注意:不过,您将丢失数组中的最后一个元素。


R
Richie Bendall

您可以对 Array#at 使用相对索引:

const myArray = [1, 2, 3]

console.log(myArray.at(-1))
// => 3

截至 2021 年 3 月,它仍在提案中,不受任何浏览器支持
现在在 chrome92 上支持它。 chromestatus.com/feature/6123640410079232
很好的答案,但如果有人说这是一种新方法,并非所有现代浏览器都完全支持,旧浏览器也不支持,那就更好了。
@M.Justin 有一个包含浏览器支持表的文档链接——应该足够了。我希望突出显示最现代的解决方案。大多数东西都可以自动填充或转译到旧环境中。在一个快速发展的生态系统中,开发人员可能应该重新考虑手动为旧环境编写代码,或者假设所有地方都支持一切。
B
BuZZ-dEE
const lastElement = myArray[myArray.length - 1];

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


这如何为最佳答案添加任何内容?
a
alex

你可以使用这个模式...

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

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


i
illright

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

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

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

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


这不是返回数组中的最后一个元素,而不是最后一个元素本身吗?
@tozazaburo 不是一回事吗?
这会修改数组。您可以使用 slice(-1) 而不是 splice(-1) 保持原始数组不变。 @AramKocharyan 不,不是,比较 ["hi"]"hi"
a
akhtarvahid

在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) let copyArr = [...arr]; console.log(copyArr.reverse()[0]);

修改原始数组

var arr = [1,2,3,4,5]; console.log(arr.pop()) arr.push(5) console.log(...arr.splice(-1));

通过创建自己的辅助方法

让 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]) - 恭喜,您刚刚修改了原始数组。
M
Mohoch

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

您可以在底部阅读有关它的更多信息here

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

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


不过,Slice 返回一个数组,因此请使用 arr.slice(-1)[0],如 this answer
如果性能是一个问题,请知道此方法比 array[array.length - 1] jsperf.com/get-last-item-from-array/13 慢很多
P
Paul Parker

这个问题已经存在了很长时间,所以我很惊讶没有人提到在 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] 慢两倍,但您不必用索引来填充。这在任何一天都值得黄金。

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

[方法].......[ETU 5 elems]...[ETU 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 的比率。尽管如此,没有人喜欢资源猪。


如果初始数组可以为空,则此方法将导致错误,[] 将变为 [undefined]。您需要使用明确的 undefined 检查来保护向后推送,例如 myPop !== undefined && arr.push(myPop)
s
sidgujrathi

只是在这里放另一个选择。

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

我发现上述方法在网上更简洁、更简短。请随意尝试这个。

注意:它会修改原始数组,如果不想修改可以使用slice()

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

感谢@VinayPai指出这一点。


in 2012 开始,已多次给出 .slice(-1) 答案,其含义已详细讨论(与此处不同)。请不要为了获得一些支持而给出重复的答案。
@DanDascalescu 谢谢你的客气话。这是一个诚实的错误,我之前在同一个问题上没有看到那个答案,并试图帮助我知道的。此外,如果upvotes 是我的摩托,那么您会在我的个人资料上看到更多重复的答案。
@DanDascalescu 无论如何,鼓励平台上的新成员的方式,以及展示他们错误的非常好的方式。向你致敬。来自如此强大的形象,倡导者,联合创始人非常鼓舞人心,我当然尽量不追随这样的影响者,并保持我的礼貌,让新成员感到舒服。谢谢你的课。这是一个很好的;)
g
gautamits

ES6 对象解构是另一种方法。

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

您可以使用对象解构从 Array 中提取长度属性。您使用已通过 [length-1] 提取的密钥创建另一个动态密钥,并将其分配给最后一个,全部在一行中。


谢谢,你能解释一下它到底是做什么的吗?
据我了解(我可能错了) length 是数组的第一个索引。但 [length-1] 是最后一个索引(它之前的那个)。 :last 是用于定义最后一个索引的别名(或者确切地说是第一个索引之前的那个)
@TarunNagpal 数组就像对象一样,它们具有长度属性和索引作为属性。这里我们析构 length 然后使用 computed property name [length -1] 来获取最后一个元素。
R
Ran Turner

可以通过 length 属性获取最后一项。由于数组计数从 0 开始,您可以通过引用 array.length - 1 项来选择最后一项

常量 arr = [1,2,3,4]; const last = arr[arr.length - 1];控制台.log(最后); // 4

另一种选择是使用新的 Array.prototype.at() 方法,该方法采用整数值并返回该索引处的项目。负整数从数组中的最后一项开始倒数,所以如果我们想要最后一项,我们可以传入 -1

常量 arr = [1,2,3,4];常量最后 = arr.at(-1);控制台.log(最后); // 4

另一种选择是使用新的 findLast 方法。您可以看到提案 here

常量 arr = [1,2,3,4]; const last = arr.findLast(x => true);控制台.log(最后); // 4

另一种选择是使用 Array.prototype.slice() 方法,它将数组的一部分的浅拷贝返回到新的数组对象中。

常量 arr = [1,2,3,4]; const last = arr.slice(-1)[0];控制台.log(最后); // 4


为什么这个帖子有-1???
imo 它应该是 arr.findLast(() => true);,因为您的版本不会“找到”像 0"" 这样的虚假值,...
我更新了我的答案@Thomas,感谢您的精彩评论。
d
devios1

对于那些不怕重载 Array 原型的人(并且您不应该使用 enumeration masking):

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

L
Lucio Paiva

如果您来这里寻找它,这里有更多 Javascript 艺术

本着使用 reduceRight() 但更短的另一个答案的精神:

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

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

请注意,这应该被视为 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("."));

n
niels

我通常使用underscorejs,你可以这样做

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

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


C
Cees Timmerman

jQuery 巧妙地解决了这个问题:

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

A
Alexandr Malinin

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

Array.from(myArray).pop()

大部分浏览器都支持 (ES6)


И
Илья Зеленько

In ECMAScript proposal Stage 1 建议添加将返回最后一个元素的数组属性:proposal-array-last

句法:

arr.lastItem // get last item
arr.lastItem = 'value' // set last item

arr.lastIndex // get last index

您可以使用 polyfill

提案作者:Keith Cirkelchai 个作者)


A
Auax

我认为这应该可以正常工作。

var arr = [1, 2, 3];
var last_element = arr.reverse()[0];

只需反转数组并获取第一个元素。

编辑:如下所述,原始数组将被反转。为避免这种情况,您可以将代码更改为:

var arr = [1, 2, 3];
var last_element = arr.slice().reverse()[0];

这将创建原始数组的副本。


这将改变原始数组
slice() 复制数组 var arr = [1, 2, 3]; last_element = arr.slice().reverse()[0];
@Zellius 如果要对数组进行切片,也可能只弹出最后一个元素。即arr.slice().pop()
M
Michael Falck Wedelgård

就个人而言,我会赞成 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]

C
Community

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

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

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

animals.reverse()[0]
"cat"

animals.reverse()[0]
"dog"

animals.reverse()[1]
"dog"

animals.reverse()[1]
"cat"

这可能是最难调试的代码类型!


如果您确实想要数组的反向 copy,您现在可以使用扩展运算符。例如[...animals].reverse()
您可以在使用反向 [1,3,4,5,"last"].slice().reverse()[0] 之前简单地复制数组