Does Underscore.js have a findLast()
method or equivalent?
What is the best way to do .find()
but return the last item that matches in Collection?
Does Underscore.js have a findLast()
method or equivalent?
What is the best way to do .find()
but return the last item that matches in Collection?
Reverse the list and then use find
:
_.find(list.slice().reverse(), iterator);
Read MDN for the documentation on reverse
.
Unfortunately a collection in underscore may be either an array or an object. If your collection is an array then you're in luck. You can use reverse
. However if it's an object then you'll need to do this instead:
_.find(Object.keys(list).reverse(), function (key) {
return iterator(list[key], key, list);
});
You could write a findLast
function for yourself:
_.mixin({
findLast: function (list, iterator, context) {
if (list instanceof Array)
return _.find(list.slice().reverse(), iterator, context);
else return _.find(Object.keys(list).reverse(), function (key) {
return iterator.call(context, list[key], key, list);
});
}
});
Now you can use findLast
like any other underscore method.
Underscore 1.8.0 introduced a method findLastIndex which can be used to accomplish this.
var numbers = [1, 2, 3, 4];
var index = _.findLastIndex(numbers, isOddNumber);
if (index > 0) { console.log(numbers[index]); }
// returns 3
Using reverse
, as suggested by @AaditMShah, is the easiest solution, but be aware that it manipulates the array in place. If you need to preserve the order of elements, you'd have to call reverse
a second time, after you are done.
If you don't want to use reverse
, you can
_.findLast
findLast
and forEachRight
and make your own findLast.This is what it looks like if you only deal with arrays and don't care about objects:
function findLast (array, callback, thisArg) {
var index = array.length,
last;
callback = callback && typeof thisArg == 'undefined' ? callback : _.bind(callback, thisArg);
while (index--) {
if (callback(array[index], index, array) == true) {
last = array[index];
break;
}
}
return last;
}
(It works, but I haven't tested it properly. So to anyone reading this, please run a few tests first and don't just copy the code.)