Doug Fir
Doug Fir

Reputation: 21282

Use array.pop() twice in a row to get second last element

var path = document.location.pathName;
example.com/store/order/cats

Sometimes it might be:

example.com/store/order/cats/

Note the slash at the end.

I'd like a function to return cats in either case. If there is no trailing slash I go:

function() {
    return path.split('/').pop();
}

But if there is a trailing slash, I need to pop() twice. I tried this:

function() {
        return path.split('/').pop().pop();
    }

Which threw an error.

So the array arising from split('/') can be either:

["", "store", "order", "cats", ""] // trailing slash

or

["", "store", "order", "cats"] // no trailing slash

How can I return cats in either eventuality?

Upvotes: 2

Views: 7241

Answers (7)

jgmjgm
jgmjgm

Reputation: 4705

There are indeed many ways to skin a cat. These assume you want one liners rather than something more defensive and that performs well.

If you always want the second from last

[1,2,3,4,5].slice(-2).shift()
4

This will likely perform very slightly better:

[1,2,3,4,5].slice(-2, -1)[0]
4

To extract all non-empty delimited items:

'/a/b//c/d/'.match(/[^\/]+/g)
[a, b, c, d]

Upvotes: 2

Edoardo L'Astorina
Edoardo L'Astorina

Reputation: 7285

As you can see in this JSFiddle http://jsfiddle.net/zarjay/mbggs/ pop is a lot more efficient than RegExp

Have a look at this bit of code now:

function( ) {
  var paths = path.split( "/" ),
      cats = paths.pop( );

  if( !cats ) {
    cats = paths.pop( );
  }

  return cats;
}

You see after you pop paths the first time, you remove the last element of the array

Now if you find that that element is empty, you just pop again and you get the element you want

Your performance is going to be a lot better and if you ever use this in a loop with thousands of iterations you'll get a performance boost in the order of seconds

And that's neat

Upvotes: 1

Pavel Gatnar
Pavel Gatnar

Reputation: 4053

Array.pop() returns the last element, not the original Array. So the second pop() is called on the last element. If it does not have pop method, you get an error...

To get the second path element from the end use path.replace(/.*\/([^\/]+)\/([^\/]+)\/?$/,'$1')

Upvotes: 1

elad.chen
elad.chen

Reputation: 2425

This is by far the simplest approach:

// Couldn't resist :)
function getCats( location ) {
    if ( location.charAt( location.length-1 ) == "/" ) {
        location = location.slice(0, -1)
    }

    return location.split("/").pop()
}

Upvotes: 1

Sam
Sam

Reputation: 3170

As others have said, you could try removing the last character if it is a slash, and then using the first method.

function getLastWordInPathName() {
  var path = document.location.pathName.replace(/\/$/, '');
  return path.split('/').pop();
}

However, your question was asking why you can't call pop() twice.

The first time you call pop(), the value of the last element in the array is returned. When you call pop() again, this function is applied to the result of the previous function - so you are calling pop() on the string '/', and not on your array.

Upvotes: 3

Tushar
Tushar

Reputation: 87203

You can first remove the last trailing / from the string and then use pop on the resulting string.

var path = document.location.pathName.replace(/\/$/, '');

var pathName = path.split('/').pop();

The regex \/$ will match the trailing / from the string. The / need to escape by preceding with \.

You can also use string methods as follow:

if (path.charAt(path.length - 1) === '/') {
    path = path.substr(0, path.length - 1);
}

Upvotes: 1

Pointy
Pointy

Reputation: 413826

You can just iterate and throw away empty path elements at the end:

function pathTail(path) {
  for (var split = path.split("/"), tail = split.pop(); !tail; tail = split.pop());
  return tail;
}

Or you can use a regular expression:

function pathTail(path) {
  return path.replace(/^.*\/([^/]+)\/*$/, "$1");
} 

Upvotes: 0

Related Questions