772

I'm making an application that updates a user's location and path in real time and displays this on a Google Map. I have functionality that allows multiple users to be tracked at the same time using an object, which is updated every second.

Right now, when a user pressed a button in the Android app, the coordinates are sent to a database and each time the location changes, a marker is updated on the map (and a polyline is formed).

Since I have multiple users, I send a unique and randomly generated alphanumeric string so that I can display an individual path for each user. When the JS pulls this data from the database, it checks if the user exists, if it does not, it creates a new key with the value being a list. It would look something like this:

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)]}

What I'm doing is storing a list of coordinates as the value of the key, which is the user's ID. My program keeps updating this list each time the location is changed by adding to the list (this works properly).

What I need to do is update the marker's location each time the location changes. I would like to do this by selecting the last item in the array since that would be the last known location. Right now, each time the location is changed a new marker is added to the map (each one of the points in the example would show a marker at that location) so markers continue to be added.

I would use a ´for (x in loc)` statement each time the location updates to grab the last location from the list and use that to update the marker. How do I select this last element from the array within the hash?

Sebastian Zartner
  • 18,808
  • 10
  • 90
  • 132
mkyong
  • 12,497
  • 12
  • 37
  • 56
  • @tomdemuyt: `loc` is not an array OP is asking about. `loc['f096012e-2497-485d-8adb-7ec0b9352c52']` (or `loc['f096012e-2497-485d-8adb-7ec0b9352c52']`) is. – zizozu Jan 29 '12 at 02:35
  • 2
    How about storing your locations in reverse order and calling loc[0]? – Christophe Jan 29 '12 at 02:38
  • 1
    @Christophe I thought about that too, but if he's tracking them for a while, he'll easily get over 1,000 locations, and performance could be an issue. Appending to the end is much quicker than moving them down. – Levi Morrison Jan 29 '12 at 02:41
  • 3
    @LeviMorrison: If altering the array is an option, then you can simply use `unshift()`, which should be a lot faster than manually "moving" elements. To have only 1000 elements in the array, and to add them at the beginning, just use the following (where `arr` is the array storing elements you want to store): `arr.unshift(new_element); arr.splice(1000);`. `unshift()` adds element at the beginning of the array, and `splice(1000)` deletes everything after first 1000 elements (if the array is shorter, it does not delete anything). Does it suit your needs? – Tadeck Jan 29 '12 at 03:02
  • 1
    Using `.length-1` is going to be [the fastest](http://jsperf.com/last-array-element2) it looks like. – Qix - MONICA WAS MISTREATED May 06 '14 at 01:01

13 Answers13

1102

How to access last element of an array

It looks like that:

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

Which in your case looks like this:

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

or, in longer version, without creating new variables:

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

How to add a method for getting it simpler

If you are a fan for creating functions/shortcuts to fulfill such tasks, the following code:

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

will allow you to get the last element of an array by invoking array's last() method, in your case eg.:

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

You can check that it works here: http://jsfiddle.net/D4NRN/

user229044
  • 232,980
  • 40
  • 330
  • 338
Tadeck
  • 132,510
  • 28
  • 152
  • 198
  • 5
    To be honest, if this is a critical part of his application, which it seems to be, he should be using objects, not just prototyping primitives. See [my post](http://www.stackoverflow.com/a/9050560/538216). – Levi Morrison Jan 29 '12 at 03:03
  • 29
    @LeviMorrison: Your answer is more about organizing the script / project, not about solving this specific issue. Adding (custom) function to the prototype may not be so clean, but let's be honest: `arr[arr.length - 1]` is the common and well-understood way of accessing last element of `arr` array. – Tadeck Jan 29 '12 at 03:07
  • This is true, but I DO solve his problem, and hopefully I save him from some others by using objects. I'm not taking away from this solution at all. Prototyping can be very useful. I just don't think it's the best option here. – Levi Morrison Jan 29 '12 at 03:10
  • 1
    @LeviMorrison: I do not say you do not solve the question. In fact, you do solve the question by a single line from your solution: `return this.locations[this.locations.length - 1];`. The rest is just a proposal on how to structure the script. And I totally agree with the way you organized this code - I use similar (or even the same) approach in even simple scripts I need to write for applications developed by me, even if the sole task is to add some UI effects / animations. – Tadeck Jan 29 '12 at 03:18
  • This works like you said, but what I didn't realize is that it does not remove the old marker. How would I remove the previous marker each time? – mkyong Jan 29 '12 at 03:19
  • @Alex If you want to remove the previous marker, just use `array.pop()`. – Levi Morrison Jan 29 '12 at 03:21
  • @Alex: Which previous marker? The one just before the last one (the one at the position `my_array.length - 2`) or the one at the beginning of the array (the oldest one)? – Tadeck Jan 29 '12 at 03:21
  • Methods added to Array.prototype should be non-enumerable, so you should use Object.defineProperty –  Aug 21 '13 at 02:19
  • @nus That doesn't work in IE8. And that's basically covering for user-error (using for/in loops on arrays rather than forEach). Not sure how I feel about that, (IMO, in JS learning the "hard" way doesn't waste a lot of time typically) but it's debatable. The IE8 thing would be the main show-stopper for me on that strategy. – Erik Reppen Mar 12 '14 at 13:21
  • This code will fail if array is empty. – Sergey Yarotskiy Jun 19 '14 at 20:05
  • 1
    @SergeyYarotskiy: I do not agree with " _This code will fail if array is empty_ ". If array is empty, the method will return `undefined`, which is more appropriate than any other value I can think of. Very simple, probably very fast, and resorts to standard behavior (using `undefined` when something is not found). – Tadeck Jun 19 '14 at 22:27
  • This is the most efficient way except `array[elements-1]`, which is unpredictable with unknown numbers. – chenghuayang Sep 01 '15 at 07:39
  • This is not a safe way to use ```this```. – imrek Apr 11 '16 at 07:58
  • 7
    It's an old answer, but especially now please avoid mutating any builtin prototypes (e.g. `Array.prototype.last = ` is an unsafe assignment). – Josh from Qaribou Oct 01 '16 at 09:24
  • 17
    I’m not the first person to say this and I won’t be the last: Don’t modify objects you don’t own—especially not native prototypes. What happens when JavaScript comes around to implementing the same method name in ES spec but it’s slightly different from yours? Bad things. Prototype and Sugar.js both modify natives. In the end they’ve both cost me and the people I work with more time and money than they saved. – Adam Sep 12 '17 at 21:47
  • If you're into the whole map reduce thing... try `myArray.reduce((acc, curr) => curr, null)`. It saves you the trouble of referencing your array twice. – Anthony De Smet Mar 15 '19 at 19:24
  • 11
    I always wondered why can't JavaScript reduce it from `this.locations[this.locations.length-1]` to `this.locations[-1]`. Wouldn't that make our life a little easier? Any reason not to? – newman Mar 15 '20 at 13:44
  • 1
    @newman the reason not to is because it will break all code that relies on item at index -1 (or any other index outside of array bounds) being undefined, skipping explicit bounds checking. – riv Apr 19 '21 at 17:10
  • I would suggest using the function on its now and avoid polluting the prototype. Also, non obvious way is `const last = (arr) => arr.slice(-1)[0];` – vamsiampolu Jun 12 '21 at 12:13
703

Use the slice() method:

my_array.slice(-1)[0]
the
  • 21,007
  • 11
  • 68
  • 101
Datageek
  • 25,977
  • 6
  • 66
  • 70
183

You can also .pop off the last element. Be careful, this will change the value of the array, but that might be OK for you.

var a = [1,2,3];
a.pop(); // 3
a // [1,2]
Maxime Lorant
  • 34,607
  • 19
  • 87
  • 97
Josh
  • 8,329
  • 4
  • 36
  • 33
  • 3
    Slowly, check out the test http://jsperf.com/last-element-of-array-xxx/2 – Josef Ježek Apr 07 '15 at 15:23
  • 62
    @JosefJezek: Yeah, slower. But, I mean, you can still do like 200 million of these in one second, so probably best to worry about what's the most readable and not worry about performance, in this case. (Unless you're trying to do hundreds of millions of them a second, of course) – Colin DeClue Jun 15 '15 at 18:02
  • 2
    Just use `arr.concat().pop()` – ife May 12 '20 at 08:26
82

use es6 deconstruction array with the spread operator

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

note that yourArray doesn't change.

hamecoded
  • 1,065
  • 7
  • 5
  • 58
    wouldn't this create a copy of `yourArray`, pop the last element and then throw the temporary copy away? I think this would be a costly operation if `yourArray` has a large number of elements. – chitti Aug 20 '17 at 03:32
  • @chitti or they just go to the last index and give you a copy of that element – magamig Jul 21 '18 at 00:55
53
var arr = [1, 2, 3];
arr.slice(-1).pop(); // return 3 and arr = [1, 2, 3]

This will return undefined if the array is empty and this will not change the value of the array.

Nery Jr
  • 3,849
  • 1
  • 26
  • 24
  • 6
    I like this. It's not going to be as fast as `arr[arr.length - 1];`, because you're instantiating a new array, but at least it's not some slow and/or destructive approach `arr.reverse()[0]` or `[...arr].pop();`, and you're not mutating a built-in prototype (very bad practice) like most of the other solutions. I'll add that nowadays you can use a destructured assignment and do away with the `pop()`, which may make sense in certain contexts. e.g. `const arr = [1,2,3]; const [last] = arr.slice(-1);` – Josh from Qaribou Oct 01 '16 at 09:19
  • Great, result is pertect . – Marcial Cahuaya May 26 '20 at 20:00
38
var last = array.slice(-1)[0];

I find slice at -1 useful for getting the last element (especially of an array of unknown length) and the performance is much better than calculating the length less 1.

Mozilla Docs on Slice

Performance of the various methods for selecting last array element

Maxime Lorant
  • 34,607
  • 19
  • 87
  • 97
amay0048
  • 961
  • 9
  • 11
  • 14
    +1 for the http://jsperf.com/get-last-item-from-array JavaScript performance link, however, for the browsers and computers I tried `array[array.length - 1]` did out perform `array.slice(-1)[0]` at least 40:1. – Stephen Quan May 01 '14 at 23:37
  • 7
    Just followed my own link and realised that I misread the graph :-P – amay0048 May 03 '14 at 02:25
38

Underscore and Lodash have the _.last(Array) method, that returns the last element in an Array. They both work about the same

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

Ramda also has a _.last function

R.last(['fi', 'fo', 'fum']); //=> 'fum'
svarog
  • 9,477
  • 4
  • 61
  • 77
19

This worked:

array.reverse()[0]
showdev
  • 28,454
  • 37
  • 55
  • 73
Sreerag
  • 313
  • 2
  • 2
  • 6
    Please explain what your code is doing. – Marco Scabbiolo Jul 26 '16 at 22:53
  • 1
    Welcome to Stack Overflow! While this code snippet may solve the question, [including an explanation](//meta.stackexchange.com/questions/114762/explaining-entirely-code-based-answers) really helps to improve the quality of your post. Remember that you are answering the question for readers in the future, and those people might not know the reasons for your code suggestion. Please also try not to crowd your code with explanatory comments, as this reduces the readability of both the code and the explanations! – Blue Jul 27 '16 at 01:10
  • 8
    Actually pretty neat idea. Javascript `reverse()`does what you would expect and the last item becomes the first which you can address by `[0]`. It's a native function available in all browsers so speed shouldn't be an issue here. **Caveat: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/reverse says it's mutating the Array. So further accessing the reversed Array might be not what you expected!** – neongrau Sep 16 '16 at 08:57
  • 25
    Besides changing the array, this will also be extremely slow. – Dan Dascalescu Sep 26 '16 at 01:46
  • if you worry about the array being mutated, reverse it back. very underrated answer! – svarog Dec 21 '16 at 13:44
  • 5
    @svarog That only adds onto the time-complexity of the answer. Unnecessarily slow. – Mox Jan 20 '17 at 15:22
  • 1
    Thanks for the contribution. The questions asks about "selecting" the last element. _Selection_ implies that the array wasn't modified in the process. The `.reverse()` method will mutate (i.e., modify) the array, which is why I downvoted your answer. – robert Feb 01 '17 at 19:26
  • Thanks, i think this is the best solution and very useful for chain function like this data[rindex-1].url.split("/").reverse()[0].split(".")[0].trim(); – Sajan Mar 24 '17 at 09:05
  • Warning, the reverse() function will change the original array! var last = ['a', 'b', 'c']; last.reverse()[0]; last.toString(); will return "c,b,a" – Manuel Romeiro Oct 26 '17 at 16:39
  • Not only it will mutate the original array, it's also an EXTREMELY costly operation as it includes recalculation of all the indexes in array! – tnsaturday Jun 16 '22 at 13:18
17

You can define a getter on 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

As you can see, access doesn't look like a function call; the getter function is called internally.

XåpplI'-I0llwlg'I -
  • 21,649
  • 28
  • 102
  • 151
17

So, a lot of people are answering with pop(), but most of them don't seem to realize that's a destructive method.

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

So, for a really silly, nondestructive method:

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

a push pop, like in the 90s :)

push appends a value to the end of an array, and returns the length of the result. so

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

pop returns the value of the last item of an array, prior to it removing that value at that index. so

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

arrays are 0 indexed, so c.length => 3, c[c.length] => undefined (because you're looking for the 4th value if you do that(this level of depth is for any hapless newbs that end up here)).

Probably not the best, or even a good method for your application, what with traffic, churn, blah. but for traversing down an array, streaming it onto another, just being silly with inefficient methods, this. Totally this.

Ryan Wood
  • 352
  • 2
  • 10
  • "So, a lot of people are answering with pop(), but most of them don't seem to realize that's a destructive method." Actually, all of them realize it's a destructive method. The answer you quoted notes it clearly in bold, while every other answer that involves pop makes a copy of the array first. – MarredCheese Jan 19 '19 at 17:49
15

In case you are using ES6 you can do:

const arr = [ 1, 2, 3 ];
[ ...arr ].pop(); // 3
arr; // [ 1, 2, 3 ] (wasn't changed)
Mykhailo Zhuk
  • 779
  • 6
  • 11
13

Use JavaScript objects if this is critical to your application. You shouldn't be using raw primitives to manage critical parts of your application. As this seems to be the core of your application, you should use objects instead. I've written some code below to help get you started. The method lastLocation would return the last location.


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);
Levi Morrison
  • 19,116
  • 7
  • 65
  • 85
  • 2
    I'm trying to use this to reorganize my program. I'm new to JS, but this is much cleaner than what I currently have. Could you explain this a little bit? Like if I were to pull coordinates and a user ID from a database, how would I trigger the program? I am using AJAX to keep calling a program that pulls coordinates from my database. – mkyong Jan 31 '12 at 09:42
  • @Alex Basically, you would make an AJAX call to get the users and their locations. You then have a class or method of a class that translates it into the objects I define here. You could have a `retreive` or some other class that makes the ajax call and calls `createUser` and sets the locations properly. Does that make sense? – Levi Morrison Jan 31 '12 at 19:41
  • 37
    Primitives are fine for simple operations. OO is not needed everywhere. – Casey Rodarmor Aug 28 '14 at 17:28
  • You don't need to create a Users class for this - it could be static behavior in the User class. If you need more than one group of users to be managed individually, I would create a Group class, but I would never name a factory class as the plural form of its product. It becomes confusing, especially when you start naming instance variables "u", "user" and "users" in your code. Anyway, I would just use arrays in this case. – Domino Feb 18 '15 at 15:15
  • 2
    This is one way to do it right. Objects tends to make the code clear and easy to use. But something is wrong here : You don't use prototype for your function definition. This is bad for performance, always use the prototype property when defining functions. Else functions are added "on the fly" everytime you create this object. – Larta May 09 '15 at 12:16
  • 2
    "You shouldn't be using raw primitives to manage critical parts of your application." What is the rationale here? – atlefren Dec 16 '15 at 08:45
  • @atlefren Do a google search to learn about "primitive obsession". – Levi Morrison Dec 16 '15 at 14:33
  • 12
    @LeviMorrison Well, I guess that is one standpoint. Although I disagree. The courses I took on progamming languages stressed the fact that functional programming languages tend to operate on primitives and sets/lists and dictionaries. This works perfectly fine, and as a consider JS more of a functional language than an OO one, I don't see the need to introduce "objects" just for the case of fulfilling someones opinion on programming in general – atlefren Dec 16 '15 at 15:01
5
var last = function( obj, key ) { 
    var a = obj[key];
    return a[a.length - 1];
};

last(loc, 'f096012e-2497-485d-8adb-7ec0b9352c52');
zellio
  • 31,308
  • 1
  • 42
  • 61
  • 1
    @LeviMorrison: In this case you can add a method to `Array`'s prototype as well. – Tadeck Jan 29 '12 at 02:17
  • 2
    @LeviMorrison: See my answer for the way that adds new method to all the arrays, so getting last element is easier. – Tadeck Jan 29 '12 at 02:26
  • 1
    Having a top-level fn like this answer suggests is better than adding a method to the prototype because it doesn't obscure access through encapsulation. – Dennis Hackethal Jun 18 '20 at 23:46