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?
3 Answers
Reset to default 13Reverse 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 acplish 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
- use Lodash instead, which provides
_.findLast
- grab the relevant code from Lodash, spread out over
findLast
andforEachRight
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.)