I want to be able to set a property on all objects inside of an array like this:
var items = [{ a: 1 }, { a: 2 }, { a: 3 }];
_.each(items, set('a', 4));
// result should be [{ a: 4 }, { a: 4 }, { a: 4 }]
I tried to acplish this by using _.rearg
on _.set
to change the parameter that takes the object to the last one like this:
var set = _.rearg(_.set, [2, 0, 1]);
However, I cannot get _.curry
to work on top of calling _.rearg
.
var set = _.curry(_.rearg(_.set, [2, 0, 1]));
set('a', 3, { a: 4 })
// returns Object {a: 3} correctly
set('a', 3)
//returns undefined, should be a function
So the desired result of being able to call it like this set('a', 3)({ a: 2 })
throws an error because it does not return a function.
How do I acplish this using lodash? I must be missing something.
I want to be able to set a property on all objects inside of an array like this:
var items = [{ a: 1 }, { a: 2 }, { a: 3 }];
_.each(items, set('a', 4));
// result should be [{ a: 4 }, { a: 4 }, { a: 4 }]
I tried to acplish this by using _.rearg
on _.set
to change the parameter that takes the object to the last one like this:
var set = _.rearg(_.set, [2, 0, 1]);
However, I cannot get _.curry
to work on top of calling _.rearg
.
var set = _.curry(_.rearg(_.set, [2, 0, 1]));
set('a', 3, { a: 4 })
// returns Object {a: 3} correctly
set('a', 3)
//returns undefined, should be a function
So the desired result of being able to call it like this set('a', 3)({ a: 2 })
throws an error because it does not return a function.
How do I acplish this using lodash? I must be missing something.
Share Improve this question asked Feb 12, 2016 at 20:14 DerekMT12DerekMT12 1,35911 silver badges15 bronze badges5 Answers
Reset to default 1The _.curry
function accepts an argument arity
that you should probably set to 3
:
_.curry(func, [arity=func.length])
Creates a function that accepts arguments of
func
and either invokesfunc
returning its result, if at leastarity
number of arguments have been provided, or returns a function that accepts the remainingfunc
arguments, and so on. Thearity
of func may be specified iffunc.length
is not sufficient.
The result from _.rearg
has a length value of zero but the underlying function requires three parameters, so you will need to specify that manually:
var set = _.curry( _.rearg(_.set, [2, 0, 1]), 3 );
Here's a live demo: http://codepen.io/anon/pen/qbgmPq
if your items is
var items = [{ a: 1 }, { a: 2 }, { a: 3 }];
then for lodash _.each and _.set, it would be like this
_.each(items, function(item){
_.set(item, 'a', 4);
});
what you are trying to do is, looking up a property 4 on item a, where it doesn't know when a is or 4 is. hope it helps.
Iterating through the list of items and using _.set on each item works.
_.map(items,function(item){_.set(item,'a',5)});
or
_.each(items,function(item){_.set(item,'a',5)});
Codepen
The problem with rearg() es when you have to read your code six months later - deciphering the argument positions is cumbersome. Combining unary() and partialRight() gives a much clearer intent:
_.each(items, _.unary(_.partialRight(_.set, 'a', 4)));
I used _.partial
const _ = require('lodash')
const __ = {
each: bindEach,
set: bindSet,
setEach: bindSetEach,
}
function bindArg(func, ...bindArgs) {
return _.partial(func, _, ...bindArgs)
}
function bindEach(...eachArgs) {
return bindArg(_.each, ...eachArgs)
}
function bindSet(...setArgs) {
return bindArg(_.set, ...setArgs)
}
function bindSetEach(...setArgs) {
return bindEach(bindSet(...setArgs))
}
module.exports = __
const __ = require('./bindArg')
test('setEach', () => {
expect(__.setEach('c', 3)([{a: 1}, {b: 2}])).toEqual([{a: 1, c: 3}, {b: 2, c: 3}])
})