Closed sivaprabug closed 3 years ago
Before I answer your question, I should emphasize that Underscore will probably never implement eachRight
. The distinction between "forward" and "backward" iteration really only applies to arrays; in objects, any order over the keys is arbitrary, and in maps, sets and iterables (which we will add support for in Underscore 2.0), there is only one direction to choose from. In fact, for this same reason, I'm considering to drop _.reduceRight
in Underscore 2.0. "Right-first" iteration has no future for any collection type other than arrays, for which you can already use _.findLastIndex
and _.lastIndexOf
.
That said, you can patch an eachRight
into Underscore with just a few lines of code. I think the following is the most functional, future-proof and backwards-compatible way to do it:
// Demonstrating monolithic import here. Use modular imports if you're
// building a custom Underscore. In that case, make sure to also
// import 'underscore/modules/iteratee.js' for its side effects.
import _, { find, findLastIndex, findKey, isFunction, isNumber, compose, noop } from 'underscore';
// export default only needed if you're building a custom Underscore.
// In that case, this would be your eachRight.js.
export default function eachRight(collection, iteratee, context) {
// Pass the result of the iteratee to _.noop to ensure that nothing is "found"
// so that iteration continues all the way to the end.
iteratee = compose(noop, _.iteratee(iteratee, context));
// Optionally, prevent functions from being iterated as arrays. Currently,
// Underscore doesn't do this but Lodash does.
if (isFunction(collection)) {
// Force treatment as a plain object.
findKey(collection, iteratee);
} else if (collection && isNumber(collection.length)) {
// Scan the array-like collection from right to left.
findLastIndex(collection, iteratee);
} else {
// Treat the collection as a plain object (or in the future, map, set or
// iterable), just like in forward _.each.
find(collection, iteratee);
}
return collection;
}
// If you just want to extend Underscore:
_.mixin({
eachRight: eachRight,
forEachRight: eachRight
});
// (now you can use the function in chains under both names)
// Alternatively, if you are building a custom Underscore:
// In your custom `index.js`:
export { default as eachRight, default as forEachRight } from './eachRight.js';
Note that I didn't bother to reverse the order of the keys of a plain object. This is a difference from Lodash _.eachRight
and also from Underscore's _.reduceRight
, but as I said before, the order of the keys doesn't really mean anything, anyway.
Lodash also has a procedural break
like construction where the iteratee
can return false
in order to stop iteration. If you want to copy that behavior as well, you can modify the iteratee a bit:
var internalIteratee = _.iteratee(iteratee, context);
iteratee = function(value, key, collection) {
return internalIteratee(value, key, collection) === false;
};
Final note: the code I've written above supports the context
argument like in all Underscore iteration functions. Lodash used to have that as well, but dropped it in version 4.
I'll close this now on the assumption that your question is answered, but please feel free to reopen if you feel the need.
@jgonggrijp
In lodash - 2.4.1 eachRight() is different from your logic My underscorjs version is 1.6.0
Sure, there are differences, including the ones I already mentioned. So what exactly do you need, and why?
In lodash - 2.4.1 have security vulnerability issue is there so plan to use underscorejs version is 1.6.0 , in my project other functionalities support in underscorejs 1.6.0. The only problem in forEachRight only not able construct the prototype in underscorejs 1.6.0
@gsivaprabu Could you show a few lines of code that illustrate the problem?
If at all possible, I recommend that you upgrade to Underscore 1.11 or later, because 1.6 is really outdated.
@gsivaprabu Could you show a few lines of code that illustrate the problem?
If at all possible, I recommend that you upgrade to Underscore 1.11 or later, because 1.6 is really outdated.
Hi @jgonggrijp
Thanks for your valuable reply
The whole project based on 1.6 only, we update underscorejs 1.11 or later means need to re-write all modules.
Only function i struggle in lodash - 2.4.1 eachRight() only
https://lodash.com/docs/2.4.2#forEachRight
_.forEachRight(collection, [callback=identity], [thisArg])
My Scenario like below:
_.forEachRight(groupBy, this.addCreateChart, this);
Using _mixin not able to adopt the lodash 2.4.1 logic:
Ref:
https://www.npmjs.com/package/lodash/v/2.4.1
lodash 2.4.1_.forEachRight function adopt to underscorejs 1.6.0
@gsivaprabu Please give me a bit more guidance. What error(s) do you see if you use just Underscore 1.6, and what error(s) do you see if you try to mix in the eachRight
implementation I suggested? What exactly does the module look like where you pasted my eachRight
implementation?
Also, are you really sure you'd need to rewrite all modules in order to use Underscore >= 1.11? There shouldn't be any hard breaking changes between 1.6 and 1.12.
How to implement forEachRight lodash feature in underscorejs ?