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) 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);
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);
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.
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));
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)
})