选择JavaScript数组中的最后一个元素[重复]

Posted

技术标签:

【中文标题】选择JavaScript数组中的最后一个元素[重复]【英文标题】:Selecting last element in JavaScript array [duplicate] 【发布时间】:2012-02-21 10:46:07 【问题描述】:

我正在制作一个实时更新用户位置和路径并将其显示在 Google 地图上的应用程序。我的功能允许使用每秒更新的对象同时跟踪多个用户。

现在,当用户在 android 应用中按下按钮时,坐标会发送到数据库,并且每次位置发生变化时,都会在地图上更新一个标记(并形成一条折线)。

由于我有多个用户,我发送一个唯一且随机生成的字母数字字符串,以便我可以为每个用户显示单独的路径。当 JS 从数据库中提取这些数据时,它会检查用户是否存在,如果不存在,它会创建一个新键,其值为列表。它看起来像这样:

loc = f096012e-2497-485d-8adb-7ec0b9352c52: [new google.maps.LatLng(39, -86),
                                              new google.maps.LatLng(38, -87),
                                              new google.maps.LatLng(37, -88)],
       44ed0662-1a9e-4c0e-9920-106258dcc3e7: [new google.maps.LatLng(40, -83),
                                              new google.maps.LatLng(41, -82),
                                              new google.maps.LatLng(42, -81)]

我正在做的是将坐标列表存储为键的值,即用户的 ID。每次通过添加到列表中更改位置时,我的程序都会不断更新此列表(这可以正常工作)。

我需要做的是每次位置更改时更新标记的位置。我想通过选择数组中的最后一项来做到这一点,因为那将是最后一个已知位置。现在,每次更改位置时,都会向地图添加一个新标记(示例中的每个点都会在该位置显示一个标记),因此会继续添加标记。

每次位置更新时,我都会使用“for (x in loc)”语句从列表中获取最后一个位置并使用它来更新标记。如何从哈希中的数组中选择最后一个元素?

【问题讨论】:

@tomdemuyt:loc 不是 OP 询问的数组。 loc['f096012e-2497-485d-8adb-7ec0b9352c52'](或loc['f096012e-2497-485d-8adb-7ec0b9352c52'])是。 以相反的顺序存储您的位置并调用 loc[0] 怎么样? @Christophe 我也想过这个问题,但如果他跟踪它们一段时间,他将轻松获得超过 1,000 个位置,性能可能会成为问题。追加到末尾比将它们向下移动要快得多。 @LeviMorrison:如果可以选择更改数组,那么您可以简单地使用unshift(),这应该比手动“移动”元素快得多。要在数组中只有 1000 个元素,并将它们添加到开头,只需使用以下命令(其中arr 是存储要存储的元素的数组):arr.unshift(new_element); arr.splice(1000);unshift() 在数组的开头添加元素,splice(1000) 删除前 1000 个元素之后的所有内容(如果数组更短,则不会删除任何内容)。它符合您的需求吗? 使用.length-1 将是the fastest 它看起来像。 【参考方案1】:

如何访问数组的最后一个元素

看起来是这样的:

var my_array = /* some array here */;
var last_element = my_array[my_array.length - 1];

在你的情况下看起来像这样:

var array1 = loc['f096012e-2497-485d-8adb-7ec0b9352c52'];
var last_element = array1[array1.length - 1];

或者,在更长的版本中,不创建新变量:

loc['f096012e-2497-485d-8adb-7ec0b9352c52'][loc['f096012e-2497-485d-8adb-7ec0b9352c52'].length - 1];

如何添加更简单的方法

如果您喜欢创建函数/快捷方式来完成此类任务,请使用以下代码:

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

将允许您通过调用数组的 last() 方法来获取数组的最后一个元素,例如:

loc['f096012e-2497-485d-8adb-7ec0b9352c52'].last();

你可以在这里检查它是否有效:http://jsfiddle.net/D4NRN/

【讨论】:

老实说,如果这是他的应用程序的关键部分,他应该使用对象,而不仅仅是原型原语。见my post。 @LeviMorrison:您的回答更多是关于组织脚本/项目,而不是解决这个特定问题。向原型添加(自定义)函数可能不是那么干净,但老实说:arr[arr.length - 1] 是访问arr 数组的最后一个元素的常见且易于理解的方式。 这是一个旧答案,但尤其是现在请避免改变任何内置原型(例如,Array.prototype.last = 是一个不安全的分配)。 我不是第一个这么说的人,也不会是最后一个:不要修改你不拥有的对象——尤其是原生原型。当 javascript 在 ES 规范中实现相同的方法名称但与您的略有不同时会发生什么?坏事。 Prototype 和 Sugar.js 都修改了 native。最后,他们花费的时间和金钱都比他们节省的要多。 我一直想知道为什么 JavaScript 不能将它从 this.locations[this.locations.length-1] 减少到 this.locations[-1]。这不是让我们的生活更轻松吗?有什么理由不这样做?【参考方案2】:

使用slice() 方法:

my_array.slice(-1)[0]

【讨论】:

这是一个很好的答案!它可以在单行中使用(my_array 可以替换为返回数组的表达式或函数),并且您不必对 Array 原型进行全局更改。 也是extremely slow。 确实这个很慢,可以参考jsperf.com/last-element-of-array-xxx 相对慢,但不是绝对慢。比替代方案慢约 100 倍,但较慢的版本仍然在我的浏览器中每秒执行近 1000 万次。 我添加了一个test case,您可以在其中连续调用.pop().push()。似乎比 .slice(-1)[0] 快 10 倍,但仍然比直接访问慢 10 倍。【参考方案3】:

您也可以.pop 关闭最后一个元素。 小心,这会改变数组的值,但这对你来说可能没问题。

var a = [1,2,3];
a.pop(); // 3
a // [1,2]

【讨论】:

慢慢看测试jsperf.com/last-element-of-array-xxx/2 @JosefJezek:是的,慢一点。但是,我的意思是,你仍然可以在一秒钟内完成 2 亿次这样的操作,所以在这种情况下,最好担心什么是最可读的,而不是担心性能。 (当然,除非您尝试每秒执行数亿次) 只要使用arr.concat().pop()【参考方案4】:

使用 es6 解构数组和扩展运算符

var last = [...yourArray].pop();

注意 yourArray 不会改变。

【讨论】:

这不会创建yourArray 的副本,弹出最后一个元素然后扔掉临时副本吗?如果yourArray 有大量元素,我认为这将是一项代价高昂的操作。 @chitti 或者他们只是转到最后一个索引并为您提供该元素的副本【参考方案5】:
var arr = [1, 2, 3];
arr.slice(-1).pop(); // return 3 and arr = [1, 2, 3]

如果数组为空,这将返回 undefined 并且不会改变数组的值。

【讨论】:

我喜欢这个。它不会像arr[arr.length - 1]; 那样快,因为您正在实例化一个新数组,但至少它不是一些缓慢和/或破坏性的方法arr.reverse()[0][...arr].pop();,而且您不会改变内置的-在原型中(非常糟糕的做法),就像大多数其他解决方案一样。我要补充一点,现在你可以使用解构赋值并取消pop(),这在某些情况下可能是有意义的。例如const arr = [1,2,3]; const [last] = arr.slice(-1); 很好,结果很完美。【参考方案6】:
var last = array.slice(-1)[0];

我发现 -1 处的 slice 对于获取最后一个元素(尤其是未知长度的数组)很有用,而且性能比计算长度小于 1 的要好得多。

Mozilla Docs on Slice

Performance of the various methods for selecting last array element

【讨论】:

+1 为jsperf.com/get-last-item-from-array JavaScript 性能链接,但是,对于我尝试过的浏览器和计算机array[array.length - 1] 至少执行array.slice(-1)[0] 40:1。 刚刚点击了我自己的链接并意识到我误读了图表:-P【参考方案7】:

Underscore 和 Lodash 具有 _.last(Array) 方法,它返回数组中的最后一个元素。它们的工作原理相同

_.last([5, 4, 3, 2, 1]);
=> 1

Ramda 也有一个_.last 函数

R.last(['fi', 'fo', 'fum']); //=> 'fum'

【讨论】:

【参考方案8】:

这行得通:

array.reverse()[0]

【讨论】:

请解释你的代码在做什么。 欢迎来到 Stack Overflow!虽然这段代码 sn-p 可以解决问题,但including an explanation 确实有助于提高帖子的质量。请记住,您正在为将来的读者回答问题,而这些人可能不知道您的代码建议的原因。也请尽量不要用解释性 cmets 挤满你的代码,因为这会降低代码和解释的可读性! 其实很不错的想法。 Javascript reverse()做你所期望的,最后一项成为你可以通过[0]解决的第一项。它是所有浏览器都可用的本机功能,因此速度在这里应该不是问题。 警告:developer.mozilla.org/en/docs/Web/JavaScript/Reference/… 说它正在改变数组。所以进一步访问反向数组可能不是你所期望的! 除了改变数组,这也会非常慢。 @svarog 这只会增加答案的时间复杂性。不必要的慢。【参考方案9】:

如果你使用的是 ES6,你可以这样做:

const arr = [ 1, 2, 3 ];
[ ...arr ].pop(); // 3
arr; // [ 1, 2, 3 ] (wasn't changed)

【讨论】:

How slow is that? 这和Array.prototype.slice(arr).pop();一样,纯粹是为了得到最后一个元素而复制整个数组。 看起来很短,但与其他方法相比肯定慢【参考方案10】:

所以,很多人都在回答 pop(),但他们中的大多数人似乎没有意识到这是一种破坏性的方法。

var a = [1,2,3]
a.pop()
//3
//a is now [1,2]

所以,对于一个非常愚蠢的非破坏性方法:

var a = [1,2,3]
a[a.push(a.pop())-1]
//3

一种流行音乐,就像 90 年代一样 :)

push 将一个值附加到数组的末尾,并返回结果的长度。所以

d=[]
d.push('life') 
//=> 1
d 
//=>['life']

pop 在删除该索引处的值之前返回数组的最后一项的值。所以

c = [1,2,1]
c.pop() 
//=> 1
c 
//=> [1,2]

数组的索引为 0,因此 c.length => 3, c[c.length] => 未定义(因为如果您这样做,您正在寻找第 4 个值(此深度级别适用于任何不幸的新手在这里结束))。

对于您的应用程序来说,可能不是最好的,甚至不是一个好的方法,比如流量、流失等等。但是对于遍历一个数组,将其流式传输到另一个数组,只是愚蠢地使用低效的方法,this。完全是这样。

【讨论】:

“所以,很多人都用 pop() 来回答,但他们中的大多数人似乎没有意识到这是一种破坏性的方法。”实际上,他们都意识到这是一种破坏性的方法。您引用的答案以粗体清楚地说明了这一点,而涉及 pop 的所有其他答案都会首先复制数组。【参考方案11】:

您可以在Array.prototype 上定义getter:

if (!Array.prototype.hasOwnProperty("last")) 
  Object.defineProperty(Array.prototype, "last", 
    get() 
      return this[this.length - 1];
    
  );


console.log([9, 8, 7, 6].last); // => 6

如您所见,访问看起来不像函数调用; getter 函数在内部调用。

【讨论】:

修改不属于你的对象的原型是不好的做法。【参考方案12】:

如果这对您的应用程序至关重要,请使用 JavaScript 对象。您不应该使用原始原语来管理应用程序的关键部分。由于这似乎是您的应用程序的核心,您应该改用对象。我在下面编写了一些代码来帮助您入门。 lastLocation 方法将返回最后一个位置。


function User(id) 
    this.id = id;

    this.locations = [];

    this.getId = function() 
        return this.id;
    ;

    this.addLocation = function(latitude, longitude) 
        this.locations[this.locations.length] = new google.maps.LatLng(latitude, longitude);
    ;

    this.lastLocation = function() 
        return this.locations[this.locations.length - 1];
    ;

    this.removeLastLocation = function() 
        return this.locations.pop();
    ;



function Users() 
    this.users = ;

    this.generateId = function() 
        return Math.random();
    ;

    this.createUser = function() 
        var id = this.generateId();
        this.users[id] = new User(id);
        return this.users[id];
    ;

    this.getUser = function(id) 
        return this.users[id];
    ;

    this.removeUser = function(id) 
        var user = this.getUser(id);
        delete this.users[id];

        return user;
    ;




var users = new Users();

var user = users.createUser();

user.addLocation(0, 0);
user.addLocation(0, 1);

【讨论】:

我正在尝试使用它来重组我的程序。我是 JS 新手,但这比我目前拥有的要干净得多。你能解释一下吗?就像我要从数据库中提取坐标和用户 ID,我将如何触发程序?我正在使用 AJAX 继续调用从我的数据库中提取坐标的程序。 原语适用于简单的操作。并非所有地方都需要 OO。 这是一种正确的方法。对象倾向于使代码清晰易用。但是这里出了点问题:你没有使用原型来定义你的函数。这对性能不利,在定义函数时始终使用原型属性。每次创建此对象时,都会“即时”添加其他功能。 “您不应该使用原始原语来管理应用程序的关键部分。”这里的理由是什么? @LeviMorrison 好吧,我想这是一个观点。虽然我不同意。我参加的编程语言课程强调了函数式编程语言倾向于对原语、集合/列表和字典进行操作。这工作得很好,并且考虑到 JS 更像是一种功能语言而不是 OO 语言,我认为没有必要仅仅为了满足某人对编程的普遍看法而引入“对象”【参考方案13】:
var last = function( obj, key )  
    var a = obj[key];
    return a[a.length - 1];
;

last(loc, 'f096012e-2497-485d-8adb-7ec0b9352c52');

【讨论】:

@LeviMorrison:在这种情况下,您也可以在Array 的原型中添加一个方法。 @LeviMorrison:请参阅我的答案,了解向所有数组添加新方法的方式,因此获取最后一个元素更容易。 拥有像这个答案这样的*** fn 比向原型添加方法要好,因为它不会掩盖通过封装进行的访问。

以上是关于选择JavaScript数组中的最后一个元素[重复]的主要内容,如果未能解决你的问题,请参考以下文章

不使用 pop() 从数组中删除最后一个元素 [重复]

从JavaScript中的数组中选择随机数量的元素

javascript更改数组中的元素[重复]

如何从javascript中的数组中删除最后一个索引元素? [复制]

获取数组中的第一个和最后一个元素,ES6方式[重复]

javascript 删除并返回数组中的最后一个元素