选择JavaScript数组中的最后一个元素

mky*_*ong 497 javascript arrays google-maps google-maps-markers

我正在制作一个实时更新用户位置和路径的应用程序,并在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)]}
Run Code Online (Sandbox Code Playgroud)

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

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

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

Tad*_*eck 778

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

它看起来像这样:

var my_array = /* some array here */;
var last_element = my_array[my_array.length - 1];
Run Code Online (Sandbox Code Playgroud)

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

var array1 = loc['f096012e-2497-485d-8adb-7ec0b9352c52'];
var last_element = array1[array1.length - 1];
Run Code Online (Sandbox Code Playgroud)

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

loc['f096012e-2497-485d-8adb-7ec0b9352c52'][loc['f096012e-2497-485d-8adb-7ec0b9352c52'].length - 1];
Run Code Online (Sandbox Code Playgroud)

如何添加一种简化方法

如果您是创建功能/快捷方式以完成此类任务的粉丝,请使用以下代码:

if (!Array.prototype.last){
    Array.prototype.last = function(){
        return this[this.length - 1];
    };
};
Run Code Online (Sandbox Code Playgroud)

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

loc['f096012e-2497-485d-8adb-7ec0b9352c52'].last();
Run Code Online (Sandbox Code Playgroud)

你可以在这里查看它的工作原理:http://jsfiddle.net/D4NRN/

  • @LeviMorrison:您的答案更多的是关于组织脚本/项目,而不是解决这个特定问题.向原型添加(自定义)函数可能不那么干净,但说实话:`arr [arr.length - 1]`是访问`arr`数组的最后一个元素的常用且易于理解的方式. (15认同)
  • 我不是第一个说这个的人,我不会是最后一个:不要修改你不拥有的对象 - 尤其不是原生原型.JavaScript在ES规范中实现相同的方法名称时会发生什么,但它与您的略有不同?坏事.Prototype和Sugar.js都修改了原生代码.最后,他们既花费了我和我工作的人,也比他们节省了更多的时间和金钱. (7认同)
  • 说实话,如果这是他的应用程序的一个关键部分,它似乎是,他应该使用对象,而不仅仅是原型的原型.见[我的帖子](http://www.stackoverflow.com/a/9050560/538216). (3认同)
  • 这是一个古老的答案,但是特别是现在请避免更改任何内置原型(例如,Array.prototype.last =`是不安全的赋值)。 (2认同)
  • 我一直想知道为什么 JavaScript 不能将其从 `this.locations[this.locations.length-1]` 减少到 `this.locations[-1]`。这难道不会让我们的生活变得更轻松一些吗?有什么理由不这样做? (2认同)

Dat*_*eek 424

使用slice()方法:

my_array.slice(-1)[0]
Run Code Online (Sandbox Code Playgroud)

  • 它也[非常慢](http://jsperf.com/last-array-element2). (164认同)
  • 它*相对*慢,但不是*绝对*慢.比替代品慢约100倍,但较慢的版本在我的浏览器中仍然每秒执行近1000万次. (52认同)
  • 这是一个很好的答案!它可以在单行中使用(`my_array`可以由返回数组的表达式或函数替换),并且您不必对`Array`原型进行全局更改. (7认同)
  • 确实这非常慢,你可以参考http://jsperf.com/last-element-of-array-xxx (5认同)
  • 我添加了一个[测试用例](http://jsperf.com/last-element-of-array-xxx/7),你连续调用`.pop()`和`.push()`.似乎比`.slice(-1)10倍快[0]`,但仍比10倍的直接存取慢. (5认同)
  • 显然它很慢。切片创建新数组并弹出修改后的数组。直接访问只是返回 (2认同)
  • 更不用说这条线很晦涩。我不希望在代码中遇到这个问题。 (2认同)
  • 这太难读了 (2认同)

Jos*_*osh 118

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

var a = [1,2,3];
a.pop(); // 3
a // [1,2]
Run Code Online (Sandbox Code Playgroud)

  • @JosefJezek:是的,慢一点.但是,我的意思是,你仍然可以在一秒钟内完成2亿这样的事情,所以最好担心在这种情况下最可读性和不担心性能的问题.(当然,除非你试图每秒做数亿个) (36认同)
  • 慢慢地,查看测试http://jsperf.com/last-element-of-array-xxx/2 (2认同)
  • 只需使用“arr.concat().pop()” (2认同)

ham*_*ded 46

将es6解构数组与扩展运算符一起使用

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

请注意,yourArray不会更改.

  • 这不会创建`yourArray`的副本,弹出最后一个元素,然后扔掉临时副本?我认为如果`yourArray`有大量元素,这将是一个代价高昂的操作. (24认同)

Ner*_* Jr 32

var arr = [1, 2, 3];
arr.slice(-1).pop(); // return 3 and arr = [1, 2, 3]
Run Code Online (Sandbox Code Playgroud)

如果数组为空,这将返回undefined,这不会更改数组的值.

  • 我喜欢这个.它不会像`arr [arr.length - 1];`那样快,因为你实例化一个新数组,但至少它不是一些缓慢和/或破坏性的方法`arr.reverse()[0] `或`[... arr] .pop();`,你并没有像大多数其他解决方案那样改变内置原型(非常糟糕的做法).我想补充说,现在你可以使用一个结构化的赋值并取消`pop()`,这在某些情况下可能有意义.例如`const arr = [1,2,3]; const [last] = arr.slice(-1);` (4认同)

ama*_*048 24

var last = array.slice(-1)[0];
Run Code Online (Sandbox Code Playgroud)

我发现-1处的切片对于获取最后一个元素(特别是未知长度的数组)非常有用,并且性能比计算长度减去1要好得多.

片上的Mozilla文档

用于选择最后一个数组元素的各种方法的性能

  • http://jsperf.com/get-last-item-from-array JavaScript性能链接的+1,但是,对于浏览器和计算机我试过`array [array.length - 1]`没有执行`数组. slice(-1)[0]`至少40:1. (13认同)
  • 只是按照我自己的链接,意识到我误读了图:-P (5认同)

sva*_*rog 22

下划线Lodash_.last(Array)方法,返回的最后一个数组中的元素.他们都是一样的

_.last([5, 4, 3, 2, 1]);
=> 1
Run Code Online (Sandbox Code Playgroud)

Ramda也有一个_.last功能

R.last(['fi', 'fo', 'fum']); //=> 'fum'
Run Code Online (Sandbox Code Playgroud)


Lev*_*son 13

如果这对您的应用程序至关重要,请使用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);
Run Code Online (Sandbox Code Playgroud)

  • 对于简单的操作,基元很好.到处都不需要OO. (19认同)
  • @LeviMorrison嗯,我想这是一个立场.虽然我不同意.我对编程语言所采用的课程强调了函数式编程语言倾向于在基元和集/列表和字典上运行的事实.这非常合适,并且考虑到JS更多的是一种函数式语言而不是OO,我认为不需要引入"对象"只是为了满足一些人对编程的看法. (7认同)
  • 我正在尝试用它来重新组织我的程序。我是 JS 新手,但这比我目前拥有的要干净得多。您能解释一下吗?就像如果我要从数据库中提取坐标和用户 ID,我将如何触发该程序?我正在使用 AJAX 不断调用从数据库中提取坐标的程序。 (2认同)
  • 这是一种正确的方法.对象倾向于使代码清晰易用.但这里出了点问题:你没有使用原型进行函数定义.这对性能有害,在定义函数时总是使用prototype属性.每次创建此对象时,"动态"添加其他函数. (2认同)
  • “您不应该使用原始原语来管理应用程序的关键部分。” 这里的原理是什么? (2认同)

Xåp*_* - 12

您可以定义Array.prototype:

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

console.log([9, 8, 7, 6].last); // => 6
Run Code Online (Sandbox Code Playgroud)

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

  • 修改不属于您的对象的原型是不好的做法。 (5认同)

小智 10

这有效:

array.reverse()[0]
Run Code Online (Sandbox Code Playgroud)

  • 除了改变阵列,这也将非常慢. (9认同)
  • 其实很漂亮的想法.Javascript`reverse()`执行您期望的操作,最后一项成为您可以通过`[0]`解决的第一项.它是所有浏览器都可以使用的本机功能,因此速度不应成为问题.**警告:https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/reverse表示它正在改变阵列.因此,进一步访问反转阵列可能不是您所期望的!** (6认同)
  • @svarog这只会增加答案的时间复杂性.不必要的慢. (4认同)
  • 请解释一下您的代码正在做什么. (3认同)

小智 9

如果您使用ES6,您可以:

const arr = [ 1, 2, 3 ];
[ ...arr ].pop(); // 3
arr; // [ 1, 2, 3 ] (wasn't changed)
Run Code Online (Sandbox Code Playgroud)

  • [这有多慢?](http://stackoverflow.com/questions/9050345/selecting-last-element-in-javascript-array/20957854#20957854) (8认同)
  • 这与`Array.prototype.slice(arr).pop();`相同,它完全复制完整数组以获取最后一个元素. (3认同)

Rya*_*ood 6

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

var a = [1,2,3]
a.pop()
//3
//a is now [1,2]
Run Code Online (Sandbox Code Playgroud)

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

var a = [1,2,3]
a[a.push(a.pop())-1]
//3
Run Code Online (Sandbox Code Playgroud)

推出流行音乐,就像在90年代:)

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

d=[]
d.push('life') 
//=> 1
d 
//=>['life']
Run Code Online (Sandbox Code Playgroud)

pop返回数组的最后一项的值,然后在该索引处删除该值.所以

c = [1,2,1]
c.pop() 
//=> 1
c 
//=> [1,2]
Run Code Online (Sandbox Code Playgroud)

数组索引0,所以c.length => 3,C [c.length] =>未定义(因为你正在寻找的第4个值,如果你这样做(这层深度的是,在这里结束了倒霉的任何newbs )).

对于你的应用来说,可能不是最好的,甚至是一个好的方法,交通,流失,等等.但是为了遍历一个数组,将它流式传输到另一个数组,只是用低效的方法愚蠢,这个.完全是这个.


zel*_*lio 5

var last = function( obj, key ) { 
    var a = obj[key];
    return a[a.length - 1];
};

last(loc, 'f096012e-2497-485d-8adb-7ec0b9352c52');
Run Code Online (Sandbox Code Playgroud)

  • @LeviMorrison:有关将新方法添加到所有数组的方式,请参阅我的答案,因此获取最后一个元素更容易。 (2认同)