Lodash reject get return object - javascript

var obj = {a: [], b: [1,2], c: [], d: [1]};
How do I get a non-empty array of objects like the following:
{b: [1,2], d: [1]}

You can do what you are after, using pickBy().
var result = _.pickBy(obj, function(val){
return val.length > 0;
});
Fiddle here: https://jsfiddle.net/W4QfJ/3160/
Note: Unlike filter() and reject(), this returns an object, keeping your original structure (rather than an array).

Another way to do this: _.omitBy(obj, _.isEmpty);

_.filter() is what you're looking for:
var obj = {a: [], b: [1,2], c: [], d: [1]};
console.log(_.filter(obj, function(o){ return o.length; }))

If you want to use _.reject() like in your title, you can do something like this:
_.reject({a: [], b: [1,2], c: [], d: [1]},function(o){
return o.length == 0
});

Right now, Lodash has a method called _.omit that does exactly what you need:
> const object = {a: 1, b: 2, c: 3, d: 4}
undefined
> _.omit(object, ['a', 'c'])
{ b: 2, d: 4 }

Related

Object.assign(...as) changes input parameter

Object.assign(...as) appears to change the input parameter. Example:
const as = [{a:1}, {b:2}, {c:3}];
const aObj = Object.assign(...as);
I deconstruct an array of object literals as parameter of the assign function.
I omitted console.log statements. Here's the stdout from node 13.7:
as before assign: [ { a: 1 }, { b: 2 }, { c: 3 } ]
aObj: { a: 1, b: 2, c: 3 }
as after assign: [ { a: 1, b: 2, c: 3 }, { b: 2 }, { c: 3 } ]
The reader may notice that as first element has been changed in an entire.
Changing a new array bs elements to an immutable object (using freeze)
const bs = [{a:1}, {b:2}, {c:3}];
[0, 1, 2].map(k => Object.freeze(bs[k]));
const bObj = Object.assign(...bs);
leads to an error:
TypeError: Cannot add property b, object is not extensible
at Function.assign (<anonymous>)
Which indicates the argument is indeed being changed.
What really confounds me is that even binding my array, cs, by currying it to a function (I think you call this a closure in JS)
const cs = [{a:1}, {b:2}, {c:3}];
const f = (xs) => Object.assign(...xs);
const g = () => f(cs);
const cObj = g();
returns:
cs before assign: [ { a: 1 }, { b: 2 }, { c: 3 } ]
cObj: { a: 1, b: 2, c: 3 }
cs after assign: [ { a: 1, b: 2, c: 3 }, { b: 2 }, { c: 3 } ]
What went wrong here? And how may one safely use Object.assign without wrecking its first argument?
Object.assign is not a pure function, it writes over its first argument target.
Here is its entry on MDN:
Object.assign(target, ...sources)
Parameters
target
The target object — what to apply the sources’ properties to, which is returned after it is modified.
sources
The source object(s) — objects containing the properties you want to apply.
Return value
The target object.
The key phrase is "[the target] is returned after it is modified". To avoid this, pass an empty object literal {} as first argument:
const aObj = Object.assign({}, ...as);

Destructure to two separate variables

Is there a quick way to destructure an object so that it store into two different groups? for example:
const obj = {a: 1, b: 2, c:3, d: 4, e: 5};
const {a, b} = obj;
// store the rest of the properties that weren't destructed above
const {otherStuff} = obj;
Some stuff to note:
I know what are the first properties i need from the object.
I don't know what the rest of the properties are that weren't destructured.
const {a, b, ...otherStuff} = obj;
You can use destructuring with rest parameter syntax ... to get the rest of the object in another variable:
const obj = {a: 1, b: 2, c:3, d: 4, e: 5};
const {a, b, ...otherStuff} = obj;
console.log(otherStuff);

How do I take all of an object's properties and insert them into its own object array property?

For example I want something like:
{
a: 1,
b: 2,
c: 3
}
turned into:
{
d: {
a: 1,
b: 2,
c: 3
}
}
I've tried assigning a new property to that object with the object itself but it shows up as circular so I figure it's a reference instead of the actual properties instead of the actual values. I want to try something like JSON.stringify the object and assign it to the property but I don't know how to turn that string into an object format that I can assign to the property.
let firstObj = {
a: 1,
b: 2,
c: 3
}
let secondObj = {};
secondObj.d = firstObj;
console.log(secondObj);
Basically you create a new object and assign the original object to its property d.
You can use ES6 destructuting to make a shallow copy of the object and put it on a new prop:
let obj = {
a: 1,
b: 2,
c: 3
}
obj.d = {...obj}
console.log(obj)
If that's not an option you can reduce() over the objects keys to make a new object and assign it to d:
let obj = {
a: 1,
b: 2,
c: 3
}
obj.d = Object.keys(obj).reduce((newObj, k) => {
newObj[k] = obj[k]
return newObj
},{})
console.log(obj)
It depends whether you want to make the deep or shallow copy of the object d. (Can the object d have a nested structure?)
The question about efficient ways to clone the object has already been answered here.

lodash: deep copy object but not all properties

Is there any way to copy an object with lodash, but not all properties.
The only way I know is manually copying it property by property
wanted e.g.:
var obj = {
a: 'name',
b: [1,2,3],
c: {
z: 'surname',
x: []
},
d: {
y: 'surname2',
w: []
}
};
and the result be like
var copy_obj = {
b: [1,2,3],
c: {
z: 'surname',
x: []
}
};
Edit:
I finally opted for:
var blacklist = ['a','d'];
_.cloneDeep(_.omit(obj, blacklist));
The omit serves almost this exact purpose:
_.cloneDeep(_.omit(obj, blacklist));
Fiddle here: https://jsfiddle.net/c639m9L2/
You could use the pick function:
_.pick(obj, 'b', 'c')
You can use the second parameter to JSON.stringify to do this.
JSON.parse(JSON.stringify(obj, ['b', 'c']))
You can use a combination of assign and pick
Object.assign(copy_obj, _.pick(obj, ['b', 'c']));
In this way if copy_obj has other properties you don't override them.
var blacklist = ['a','d'];
_.cloneDeep(_.omit(obj, blacklist));

Reactjs: Is it necessary to copy object in component state before modifying it?

Suppose my my reactjs component has two states:
a: {
a: 1
},
b: [1, 2, 3]
Now I want them to become:
a: {
a: 1,
b: true
},
b: [1, 2, 3, 4]
Is it correct to do it by:
this.state.a.b = true;
b = this.state.b.push(4);
this.setState({
a: this.state.a,
b: b
});
If not, what is the appropriate way to do it.
Best way to do it.
this.setState({
a: Object.assign({}, this.state.a, { b: true }),
b: [...this.state.b, 4]
});
The state properties should be replaced, and not mutated:
this.setState({
a: { // create new a object
a: this.state.a.a,
b: true
},
b: this.state.b.concat([4]) // create new b array
});
Straight from the docs:
Do Not Modify State Directly
For example, this will not re-render a component:
// Wrong
this.state.comment = 'Hello';
Instead, use setState():
// Correct
this.setState({comment: 'Hello'});
So it is not necessary to copy an object before modifying it, if you use setState
So your code might look like this:
this.setState({
a: (this.state.a.b = true),
b: this.state.b.push(4)
})

Categories