2183

Here is my JavaScript code so far:

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);

Currently it takes the second to last item in the array from the URL. However, I want to do a check for the last item in the array to be "index.html" and if so, grab the third to last item instead.

0

64 Answers 64

13

I think this should work fine.

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

Just reverse the array and get the first element.

Edit: As mentioned below, the original array will be reversed. To avoid that you can change the code to:

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

This will create a copy of the original array.

Sign up to request clarification or add additional context in comments.

3 Comments

This will alter the original array
The slice() copies the array var arr = [1, 2, 3]; last_element = arr.slice().reverse()[0];
@Zellius Might as well just pop the last element if you're going to slice the array. i.e. arr.slice().pop()
12

Personally I would upvote answer by kuporific / kritzikratzi. The array[array.length-1] method gets very ugly if you're working with nested arrays.

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]

Comments

12

As per ES2022, You can use Array.at() method which takes an integer value and returns the item at that index. Allowing for positive and negative integers. Negative integers count back from the last item in the array.

Demo :

const href = 'www.abc.com/main/index.html';
const loc_array = href.split('/');

// To access elements from an array we can use Array.at()
console.log(loc_array.at(-1)); // This will return item at last index.

Comments

9

EDITED:

Recently I came up with one more solution which I now think is the best for my needs:

function w(anArray) {
  return {
    last() {
      return anArray [anArray.length - 1];
    };
  };
}

With the above definition in effect I can now say:

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

The name "w" stands for "wrapper". You can see how you could easily add more methods besides 'last()' to this wrapper.

I say "best for my needs", because this allows me to easily add other such "helper methods" to any JavaScript built-in type. What comes to mind are the car() and cdr() of Lisp for instance.

2 Comments

Why use a wrapper? If you have to call a w function just make the function return the last item.
w([1,2,3]).length is undefined. w([1,2,3])[1] is undefined. Does not seem like a wrapper to me. And there is a syntax error. You have an extra ';'. See stackoverflow.com/a/49725374/458321 for how to write a class wrapper (SutString class) and use reflection to populate that wrapper. Though, imho, wrappers are overkill. Better to use encapsulation, like you almost have. return { arr: anArray, last() { return anArray[anArray.length - 1]; } };. Also, w is way too generic. Call is ArrayW or something.
9

You can add a last() function to the Array prototype.

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

EDIT:

You can use a Symbol to avoid incompatibility with other code:

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

console.log([0, 1][last]());

1 Comment

If you’re going to extend built-in prototypes or polyfill a property (i.e. monkey-patch), please do it correctly: for forward compatibility, check if the property exists first, then make the property non-enumerable so that the own keys of constructed objects aren’t polluted. For methods, use actual methods. My recommendation: follow these examples which demonstrate how to add a method that behaves like other built-in methods, as closely as possible.
9

You could add a new property getter to the prototype of Array so that it is accessible through all instances of Array.

Getters allow you to access the return value of a function just as if it were the value of a property. The return value of the function of course is the last value of the array (this[this.length - 1]).

Finally you wrap it in a condition that checks whether the last-property is still undefined (not defined by another script that might rely on it).

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'

Does not work in IE ≤ 8.

1 Comment

Array.prototype.last is always undefined? The if isn't working under Chrome 36
7

Functional programming with Ramda

If you're using JS, I would suggest checking out Ramda which is a functional-programming library (like Lodash and Underscore, except more advanced and modular). Ramda provides this with R.last

import * as R from 'ramda';
R.last(['fi', 'fo', 'fum']); //=> 'fum'
R.last([]); //=> undefined

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

It further provides init, head, tail. List monster from (Learn You a Haskell)

List Monster

15 Comments

including library is not reasonable for getting last element, if I do, I would use underscorejs.org/#last
@Tebe Ramda is a newer more modern and modular version of Lodash which is the replacement for Underscore.js
yes, I tried ramda it tasted a bit not necessary overcomplicated at the first glance for me. Maybe I still don't think functional enough and will get into it when my mind will be ready for it. By the way, I see you have experience with it, how would look such code in ramda? _.chain([1,2,3]).map((val)=> { return val*2 }).first().value() -> result is 2. Does it support chaining ? I see ramda has method chain, but it looks like it's for smth else
@Tebe Like this R.pipe(R.take(1), x=>x*2) (also works with typescript)
I don't understand why this answer got so many downvotes! Ramda is arguably better than both Lodash and Underscore. It is purely functional and clean even though it might be a bit hard to understand if someone is not used to functional programming. Its definitely a good answer to the problem though I still wouldn't recommend using a library if the only thing you have to do is to get the last element in an array.
|
6

I'll suggest to create helper function and reuse it every time, you'll need it. Lets make function more general to be able to get not only last item, but also second from the last and so on.

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

Usage is simple

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

Now, lets solve the original issue

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.

Next line does the job

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

So, you'll need to rewrite

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

in this way

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

or use additional variable to increase readability

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

Comments

6

Using lodash _.last(array) Gets the last element of array.

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

Comments

6

I think the easiest to understand for beginners and super inefficient way is: 😆

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

2 Comments

This solution takes O(n) more memory and takes O(n) time. It's really not the ideal solution.
it must not start with fenerbahce. it must be like that: ['besiktas','galatasaray','trabzonspor','bursaspor','fenerbahce'] ;)
6

Normally you are not supposed to mess with the prototype of built-in types but here is a hack/shortcut:

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

This will allow all array objects to have a last property, which you can use like so:

const letters = ['a', 'b', 'c', 'd', 'e'];
console.log(letters.last); // 'e'

You are not supposed to mess with a built-in type's prototype because you never when a new ES version will be released and in the event that a new version uses the same property name as your custom property, all sorts of breaks can happen. Also, it makes it hard for others to follow your code, especially for people joining the team. You COULD make the property to something that you know an ES version would never use, like listLastItem but that is at the discretion of the developer.

Or you can use a simple method:

const getLast = (list) => list[list.length - 1];
const last = getLast([1,2,3]); // returns 3

Comments

6

Update - 27 October 2021 (Chrome 97+)

Proposal for Array.prototype.findLast is now on Stage 3!

Here's how you can use it:

const array = [1, 2, 3, 4, 5];

const last_element = array.findLast((item) => true);
console.log(last_element);

You can read more in this V8 blog post.

You can find more in "New in Chrome" series.

Comments

5

Will this work?

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

3 Comments

No because .pop() returns the last element and also removes it, so your indexes change.
If you do not want your original array to be mutated then do arr.slice().pop() - this creates a new array
better when you don't care about array anymore!
5

Using ES6/ES2015 spread operator (...) you can do the following way.

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

Please notice that using spread operator and reverse we did not mutated original array, this is a pure way of getting a last element of the array.

2 Comments

Reversing an entire array just to get the last element is super inefficient.
@slang, agree. If you are doing hundreds to millions operations then you have to consider not to do it this way, but if you have to do it only several time than nobody will notice that. This example provides 'pure' call without changing actual data array.
5

How about something like below:

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

If using Underscore or Lodash, you can use _.last(), so something like:

if ('index.html' === _.last(array)) {  
   //do this 
} else { 
   //do that 
}

Or you can create your own last function:

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

and use it like:

if ('index.html' === _last(array)) {  
   //do this 
} else { 
   //do that 
}

Comments

4

This can be done with lodash _.last or _.nth:

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

Comments

4

This method will not mess with your prototype. It also guards against 0 length arrays, along with null/undefined arrays. You can even override the default value if the returned default value might match an item in your array.

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'))

Comments

3

You can achieve this issue also without extracting an array from the url

This is my alternative

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

!Greetings¡

Comments

3

Another ES6 only option would be to use Array.find(item, index)=> {...}) as follows:

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

little practical value, posted to show that index is also available for your filtering logic.

Comments

3

This is clean and efficient:

let list = [ 'a', 'b', 'c' ]

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

If you install a pipe operator using Babel it becomes:

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

1 Comment

I love that iife syntax so much. Thank you for making my life happily more complicated.
3

Update 2020

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

let a = [1, 2, 3, [4, 5]];

console.log(a.last());
// [ 4, 5 ]
console.log(a.last().last());
// 5

Setter and Getter

Array.prototype.last = function(val=null) {
  if (this.length === 0) {
    if (val) this[0] = val;
    else return null; 
  }
  
  temp = this;
  while(typeof temp[temp.length-1] === "object") {
    temp = temp[temp.length-1];
  }
  
  if (val) temp[temp.length-1] = val; //Setter  
  else return temp[temp.length-1]; //Getter
  
}

var arr = [[1, 2], [2, 3], [['a', 'b'], ['c', 'd']]];
console.log(arr.last()); // 'd'
    
arr.last("dd"); 
console.log(arr); // [ [ 1, 2 ], [ 2, 3 ], [ [ 'a', 'b' ], [ 'c', 'dd' ] ] ]

3 Comments

Please avoid polluting prototypes.
@Sean, adding is a better practice compare to rewriting prototype.
I don't know what you're trying to say but modifying prototypes you don't own makes your code prone to conflicts and hurts forward-compatibility. Prototype pollution is a known bad practice caught by JavaScript security bulletins.
2

The arrow function makes the fastest-performing method more concise, by not repeating the name of the array.

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

2 Comments

But why write a method when you can access the last item directly... var lastItem = a[a.length-1]
This doesn't demonstrate creating a method, though. It shows off using an arrow function to "rename" loc_array to a within the context of the function. It's like doing var getLast = a => a[a.length - 1]; var lastItem = getLast(loc_array), but the "getLast" function is in-lined, not separately defined.
2
var str = ["stackoverflow", "starlink"];
var last = str[str.length-1];//basically you are putting the last index value into the array and storing it in la

Comments

1

There is also a npm module, that add last to Array.prototype

npm install array-prototype-last --save

usage

require('array-prototype-last');

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

[].last; //=> undefined 

4 Comments

source of function?
it's simalar to this? Array.prototype.last = function(){ return this[this.length - 1]; } + Object.defineProperty(Array.prototype, 'last', {enumerable: false});
in your example last is function you should call it like ['a', 'b'].last() // 'b', while in module last is property and you can call it like ['a', 'b'].last // 'b'
ok it's a trik to remove () in code, but this "property" stay in fact a function called each time, right?
1

For a readable and concise solution, you can use a combination of Array.prototype.slice and destructuring.

const linkElement = document.getElementById("BackButton");
const loc_array = document.location.href.split('/');

// assign the last three items of the array to separate variables
const [thirdLast, secondLast, last] = loc_array.slice(-3);

// use the second last item as the slug...
let parentSlug = secondLast;

if (last === 'index.html') {
  // ...unless this is an index
  parentSlug = thirdLast;
}

const newT = document.createTextNode(
  unescape(
    capWords(parentSlug)
  )
);

linkElement.appendChild(newT);

But to simply get the last item in an array, I prefer this notation:

const [lastItem] = loc_array.slice(-1);

Comments

1

ES2023 Array Method findLastIndex

The findLastIndex() method iterates the array in reverse order and returns the index of the first element that satisfies the provided testing function. If no elements satisfy the testing function, -1 is returned.

const arr = [1,2,3,4];
const lastIndex = arr.findLastIndex(x => true);
console.log(arr[lastIndex]); // 4

PS: findLastIndex() method is supported by all browsers and on Node.js version 18+.
see browser compatibility

1 Comment

This is the best option if you actually need to know the index number, but if you just want the last element then it's simpler to just use arr.at(-1) (added in ES2022). See stackoverflow.com/a/75051635/560114
1

You can use snippet that extends the functionality of arrays by adding a new method called last(). This method can be used various approach to retrieve the last item of an array. Choose one of the many possibilities:

Array.prototype.last = function() {
  return this[this.length - 1]
  // return this.slice(-1)[0]
  // return this.at(-1)
  // return this.findLast(x => true)
  // return [...this].reverse()[0]
  // return this.reduceRight(_ => _)
  // return this.slice().reverse()[0]
  // return this.pop()
  // return this.splice(-1,1)[0]
  // return [...this].pop()
  // return this.find((_,i,a)=>a.length==i+1)
}


console.log([2,4,6].last()) // 6
console.log([1, 2, 3].last()) // 3

Comments

0

Using reduceRight:

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

2 Comments

This is actually a pretty creative way of doing it, although it does run in O(n) time because it still traverses the whole array.
If you don't mind, I made it even more concise by removing the unnecessary return and curly braces.
0

simple answer

const array = [1,2,3]
array[array.length - 1]

1 Comment

Very good answer
0

The pop() and slice() both method are faster. You can use pop() method if you are fine with modifying the array. If you don't want to change the array, the slice() method can be used.

let arrItems = [12, 24, 60, 80, 10, 14, 123];
console.time('using array length');
let lastItem = arrItems[arrItems.length - 1];
console.log(lastItem);
console.timeEnd('using array length');

console.time('using slice method');
let lastItem1 = arrItems.slice(-1)[0];
console.log(lastItem1);
console.timeEnd('using slice method');

console.time('using pop method');
let lastItem2 = arrItems.pop();
console.log(lastItem2);
console.timeEnd('using pop method');

//Output:

//123
//using array length: 0.200ms
//123
//using slice method: 0.175ms
//123
//using pop method: 0.012ms

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.