feihcsim
feihcsim

Reputation: 1552

How can I find an array element starting from the end of the array?

JavaScript has array methods like indexOf and find for getting the first element in the array that matches the criteria. The counterpart to indexOf would be lastIndexOf, which searches starting from the end of the array instead. I'm wondering now if there is a counterpart to find that starts from the end of the array, like a native implementation of Ramda's findLast.

I would prefer to use neither array.slice().reverse().find() due to performance costs nor a for loop as it is verbose and not in the spirit of functional programming

Upvotes: 1

Views: 2159

Answers (3)

ggorlen
ggorlen

Reputation: 56925

You can use reduceRight, which is in the spirit of functional programming. However, it's not as easy (but possible) to return early upon finding a match as it is in a for loop:

const lastIndexOf = (needle, haystack) => 
  haystack.reduceRight((a, e, i) => 
    a >= 0 ? a : e === needle ? i : -1
  , -1)
;

const arr = [1,4,3,5,5,4,5];
console.log(lastIndexOf(4, arr));
console.log(lastIndexOf(2, arr));

There's also recursion, which has similar efficiency problems (stack frame overhead, no instantaneous early return, having to write a helper or extra conditionals, you'll blow the stack if the array is large...):

const lastIndexOf = (needle, haystack, idx) => 
  lastIndexOfHelper(needle, haystack, haystack.length - 1)
;

const lastIndexOfHelper = (needle, haystack, idx) => 
  idx < 0 || haystack[idx] === needle ? 
    idx : lastIndexOfHelper(needle, haystack, idx - 1)  
;

const arr = [1,4,3,5,5,4,5];
console.log(lastIndexOf(4, arr));
console.log(lastIndexOf(2, arr));

Upvotes: 2

user3666653
user3666653

Reputation: 188

Lodash has a _.findLastIndex() method which interates over a collection from right to left. https://lodash.com/docs/4.17.10#findLastIndex

Not sure as to its performance though

Upvotes: 2

Jonas Wilms
Jonas Wilms

Reputation: 138267

No there is not, but you can polyfill it easily:

 Array.prototype.findLast = function(fn) {
  for(let i = this.length - 1; i >= 0; i--) 
    if(fn( this[i], i, this )) return this[i];
  return null;
 };



console.log([5,4,3,2,1].findLast(el => el > 3));

Upvotes: 2

Related Questions