Array of objects to object of property values - javascript

I have this data:
[
{foo: 1, bar: a},
{foo: 2, bar: b},
{foo: 3, bar: c},
]
What's the simplest way to transform the data to something like
{
customLabel1 : [1,2,3],
customLabel2 : [a,b,c]
}
I come up with this
{
customLabel1: data.map((a) => {return a.foo} ),
customLabel2: data.map((a) => {return a.bar} )
}
Is there a simpler way to do this, or faster?

If you want simpler, your code is already pretty close with fat arrow syntax. You can drop the parentheses and the return keyword:
{
customLabel1: data.map(a => a.foo),
customLabel2: data.map(a => a.bar)
}
If you want faster, I think you'll have to sacrifice some simplicity. As it's written, you're looping over data twice. If you iterated once, it would look something like this:
var data = [
{foo: 1, bar: 'a'},
{foo: 2, bar: 'b'},
{foo: 3, bar: 'c'},
];
var o = {customLabel1: [], customLabel2: []};
data.forEach(a => {
o.customLabel1.push(a.foo);
o.customLabel2.push(a.bar);
});
console.log(o);

You can use this form if you dont know the keys
{
customLabel1: data.map(function(element) { return element[Object.keys(element)[0]];}),
customLabel2: data.map(function(element) { return element[Object.keys(element)[1]];})
}

You could use an object for the key mapping and iterate then.
var data = [{ foo: 1, bar: 'a' }, { foo: 2, bar: 'b' }, { foo: 3, bar: 'c' }],
labels = { customLabel1: 'foo', customLabel2: 'bar' },
result = {};
data.forEach(a => Object.keys(labels).forEach(k => {
result[k] = result[k] || [];
result[k].push(a[labels[k]]);
}));
console.log(result);

The shorter syntax of the map call can be:
data.map(el => el.prop);
Having said that, I'd define a helper function for this:
function pluck(arr, props) {
return Object.keys(props).reduce((ret, prop) => {
ret[prop] = arr.map(el => el[props[prop]]);
return ret;
}, {});
}
var ret = pluck(data, {
customLabel1: 'foo',
customLabel2: 'bar'
});

Related

extracting object from array of array using es6

how can i return an array of objects taking from array of again one more level array. I am using push.
is there any better way to achieve this
let a = [{b: [{c: "k"}]}]
let o = []
a.forEach(so => {so.b.forEach(obc => o.push(obc))})
console.log(o)
I'd use flatMap() instead:
const a = [{
b: [{
foo: 'foo'
}]
},
{
b: [{
c: "k"
},
{
bar: 'bar'
}
]
}
];
const o = a.flatMap(({ b }) => b);
console.log(o);
(but this is a relatively new method, so if you want to use it and still support older environments, be sure to include a polyfill)
Lacking that, you can also improve your existing code by using concat() with the inner array instead of iterating over each inner item:
const a = [{
b: [{
foo: 'foo'
}]
},
{
b: [{
c: "k"
},
{
bar: 'bar'
}
]
}
];
let o = [];
a.forEach(({ b }) => {
o = o.concat(b);
});
console.log(o);
Try
let a = [{b: [{c: "k"}]}]
let o =a[0].b
console.log(o)

Extract from an array of objects ones that have propertie using lodash

I have a big array of objects and i need to get the objects that have the propertie def set. No mather the value...
Thanks in advance.
You can use hasOwnProperty to check if a property is present, and Array.prototype.filter to filter only those items.
objArray = [ { def: 1, bar: 2}, { foo: 3, bar: 4}, { def: 5, bar: 6} ];
var result = objArray.filter(item => item.hasOwnProperty('def'));
console.log(result);
for es5 compatibility
objArray = [{
def: 1,
bar: 2
}, {
foo: 3,
bar: 4
}, {
def: 5,
bar: 6
}];
var result = objArray.filter(function(item) {
return item.hasOwnProperty('def')
});
console.log(result);
There is not such function in lodash although you can try following code
`let aFilteredArray = [];
_.forEach(YourArray,function(oElement){
if(!_.isEmpty(oElement.def)){
aFilteredArray.push(oElement);
}
};

Create object from forEach

I'm trying to figure out if there's a way to rewrite this code as a single object creation:
my_array = [
{key: 1, value: "foo"},
{key: 2, value: "bar"}
];
let my_obj = {};
my_array.forEach((elem) => {
my_obj[elem.key] = elem.value;
});
What I'd like to do is something like:
my_array = [
{key: 1, value: "foo"},
{key: 2, value: "bar"},
];
const my_obj = ...?
Is there a way to do a one-shot conversion that's equivalent to the forEach call?
You can achieve this using Array.prototype.reduce():
var my_array = [{key: 1, value:"foo"}, {key: 2, value:"bar"}];
var my_object = my_array.reduce(function(prev, curr) {
prev[curr.key] = curr.value;
return prev;
}, {});
console.log(my_object); // {"1": "foo", "2": "bar"}
Alternatively, using ES6 syntax:
const my_object = my_array.reduce((prev, curr) => {
prev[curr.key] = curr.value;
return prev;
}, {});
In ES6, you can use Object.assign:
const obj = Object.assign({}, ...my_array.map(x => ({ [x.key]: x.value })));
// Or:
const obj = Object.assign({}, ...my_array.map(({ key, value }) => ({ [key]: value })));
This converts each { key: foo, value: bar } to { foo: bar }, then uses Object.assign to merge them into one object. (The spread operator is used as Object.assign expects a variable list of arguments.)
You can use the reduce function. It should work like this:
my_array = [
{key: 1, value: "foo"},
{key: 2, value: "bar"}
];
let my_obj = my_array.reduce(function(obj, elem) {
obj[elem.key] = elem.value;
return obj;
}, {});
// my_obj = { "1": "foo", "2": "bar" }

Shorthand / operator for forEach, map?

Is there a shorthand for accessing properties of an array of objects?
let o = [
{id: 1},
{id: 2},
{id: 3}
];
o.map(item => item.id); // [1, 2, 3]
Instead with some type of shorthand:
o[].id; // [1, 2, 3]
If not, is there a recommendation to add such a thing in the future?
This would pretty much accomplish what i want:
Object.defineProperty(Array, 'all', {
value: function(array) {
let allProperties = new Set();
let methods = {};
array.forEach(o => {
if(!(o instanceof Object)) return;
Object.keys(o).forEach(property => {
allProperties.add(property);
});
});
allProperties.forEach(property => {
methods[property] = array.map(o => {
if(!(o instanceof Object)) return o;
return o[property];
});
});
return methods;
}
});
So that:
let o = [
{id: 1},
{id: 2},
null,
{num: 3}
];
Array.all(o).id; // [1, 2, null, undefined]
It could also extend Array.prototype so that o.all.id would return the same thing.

How to know if an object includes another one

I am trying to find a library able to say if an object B includes all property and values of an object A (and not the opposite !).
It means 2 things that the librairies i found do not handle:
The object B could have more keys than object A, and it could be
true.
The object B could have more items in its arrays than object
A, and it could be true.
This is basically what the method _.difference() of lodash does, but only for items in arrays.
i found interesting libraries like deep-diff, but anything for my need.
I could code something doing the job, but i am convinced other peoples met this need before.
Here is an example with 2 objects:
var A = {
name: 'toto',
pets: [ { name: 'woof', kind: 'dog' } ]
};
var B = {
name: 'toto',
pets: [ { name: 'gulp', kind: 'fish' }, { name: 'woof', kind: 'dog' } ],
favoriteColor: 'blue'
};
Here, A includes B since we can find in B every properties and values of A.
But librairies like diff would say no, since this is not the first but the second item of "pets" which is equal to A, and B has an additionnal property "favoriteColor".
Do you know a librairy able to do this kind of comparison?
You could use a modified version of the deepCompare that was linked in the comments. Really you just need to get past the keys length comparison, it seems.
// where b has all of a
function deepHas(a, b) {
if (typeof a !== typeof b) {
return false;
}
if (typeof a !== 'object') {
return a === b;
}
// you may need to polyfill array higher-order functions here
if(Array.isArray(a) && Array.isArray(b)) {
return a.every(function(av) {
return b.indexOf(av) !== -1;
});
}
if (Object.keys(a).length > Object.keys(b).length) {
return false;
}
for (var k in a) {
if (!(k in b)) {
return false;
}
if (!deepHas(a[k], b[k])) {
return false;
}
}
return true;
}
var a1 = {
foo: ['a', 'b', 'c'],
bar: 'bar',
baz: {
baz: {
baz: 'wee'
}
}
};
var b1 = {
foo: ['a', 'b', 'c', 'd'],
bar: 'bar',
baz: {
baz: {
baz: 'wee',
whatever: 'wat'
}
},
ok: 'test'
};
console.log('b1 has all of a1', deepHas(a1, b1));
var a2 = {
foo: ['a', 'b', 'c'],
bar: 'bar',
baz: {
baz: {
baz: 'wee'
}
}
};
var b2 = {
foo: ['a', 'b', 'c'],
baz: {
baz: {
baz: 'wee'
}
}
};
console.log('b2 does not have all of a2', !deepHas(a2, b2));
console.log('["a","b"] has ["b"]', deepHas(["b"], ["a","b"]));
console.log('{foo: ["a","b"]} has {foo: ["b"]}', deepHas({ foo: ["b"] }, { foo:["a","b"] }));

Categories

Resources