I have an array of objects. During the loop I append different properties to each entry.
My question - how do I make sure every entry has all the properties of each entry?
Let's consider this:
var myArray = [{A: 1}, {B: 2}, {C: 3}];
Now I want to run some elegant one-liner to convert this array into:
[{A: 1, B:2, C: 3}, {A: 1, B:2, C: 3}, {A: 1, B:2, C: 3}]
An elegant one-liner is a bit difficult without a library. But if you have some kind of extend function, then it could be:
myArray.map(function(v) { return extend.apply(null, [{}].concat(myArray)); });
The extend function would require several objects (passed as separate arguments) to be combined. Such a function is available in jQuery as jQuery.extend, and underscore.js also has one.
Related
This question already has answers here:
How can I group an array of objects by key?
(32 answers)
Closed 2 years ago.
This is somewhat complex for me to put into words properly, so I'll just drop an example of what I'm trying to do in terms of input and expected output below. I've tried a few things but they seem to be way more complex than needed, result in duplication issues, or flat out don't work. Thanks ahead of time for any help people can provide. And if there's already a post that answers this question, I am sorry and I'll gladly take that link - as I said, it's difficult to put this into words.
Input: Array of Objects
Ex:
[
{prop: 1},
{prop: 1},
{prop: 2},
{prop: 3},
{prop: 2}
]
OUTPUT: Array of arrays where all objects with some matching property are grouped.
Ex:
[
[{prop: 1}, {prop: 1}],
[{prop: 2},{prop:2}],
[{prop:3}]
]
Simple reduce loop with an object
var arr = [
{prop: 1},
{prop: 1},
{prop: 2},
{prop: 3},
{prop: 2}
]
const result = Object.values(arr.reduce((acc, item) => {
acc[item.prop] = acc[item.prop] || [];
acc[item.prop].push(item);
return acc;
}, {}));
console.log(result);
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.
I'm trying to figure how can I pass an object and just check if the object is in the response using either that.includes or to.include from chai
I wrote a simple fiddle to check my problem:
https://jsfiddle.net/balexandre/4Loupnjk/2/
https://jsfiddle.net/balexandre/4Loupnjk/5/ with .deep flag
var e = {
"results": {
"total_rejected_recipients": 0,
"total_accepted_recipients": 1,
"id":"102618457586465882"
}
};
from my understanding, the e object should actually have the smaller object included... or am I missing something?
expect(e).to.include({
"results": {
"total_rejected_recipients": 0,
"total_accepted_recipients": 1
}
});
but I get the error:
assertionError: expected { Object (results) } to have property 'results' of { Object (total_rejected_recipients, total_accepted_recipients) }, but got { Object (total_rejected_recipients, total_accepted_recipients, ...) }
at Context.<anonymous> (:73:18)
First time on this framework though, might be the issue :)
First of all, you should use the deep.include assertion, as you have a deep object in there.
Anyways, it looks like this is a bug. The github ticket where this was implemented is located here and the relevant commit here.
The test coverage for this assertion is here:
expect({foo: obj1, bar: obj2}).to.deep.include({foo: {a: 1}});
expect({foo: obj1, bar: obj2}).to.deep.include({foo: {a: 1}, bar: {b: 2}});
expect({foo: obj1, bar: obj2}).to.not.deep.include({foo: {a: 9}});
expect({foo: obj1, bar: obj2}).to.not.deep.include({foo: {z: 1}});
expect({foo: obj1, bar: obj2}).to.not.deep.include({baz: {a: 1}});
expect({foo: obj1, bar: obj2}).to.not.deep.include({foo: {a: 1}, bar: {b: 9}});
However, it breaks in the following scenario:
expect({ foo: obj1, bar: obj2 }).to.deep.include({ foo: { a: 1 }, bar: { } });
Better open the issue in chai repository, and temporary use the chai-subset package.
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 }