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)
Related
I have an array of objects like this:
const arrayOfObjects = [
{ A: 1, B: 2, C: 3 },
{ A: 3, B: 4, C: 1 }
]
And another array which is called "headers"
const headers = [
['A', 'B'],
['C']
]
I have to create an array similar to the first one but, with those objects splited by what headers have in it's arrays.
This should be the goal:
const result = [
[
{ A: 1, B: 2 },
{ C: 3 }
],
[
{ A: 3, B: 4 },
{ C: 1 }
]
]
I tried by doing a "base" array with:
const baseArray = []
headers.forEach((header) => {
const objFromHeader = {};
header.forEach((head) => {
objFromHeader[head] = 0;
});
baseArray.push(objFromHeader);
});
That will give me the result array but with 0 values for each key.
And then loop for the first array and put inside another array the base array with the correct values.
Then I wanted to fill each key according to the value that comes from arrayOfObjects but here is where I can't see how could I loop that array of objects and put the correct value. The only problem with that approach is that the result array will have some 0 values that come from the initiation array that I'm using, it would be better to me to only put the objects that actually have values and not 0 (I was thinking on another function to delete those keys with value = 0...)
How could I achieve it in a better way?
Fiddle:
https://jsfiddle.net/pmiranda/Lpscz6vt/
When iterating over an object, use findIndex on the headers to identify which index in the headers array the property being iterated over should go into. Create an object there if it doesn't exist yet, and set the property.
const arrayOfObjects = [
{ A: 1, B: 2, C:3 },
{ A: 3, B: 4, C:1 }
];
const headers = [
['A', 'B'],
['C']
];
const toResultItem = (object) => {
const resultItem = [];
for (const [key, value] of Object.entries(object)) {
const headersIndex = headers.findIndex(arr => arr.includes(key));
resultItem[headersIndex] ??= {};
resultItem[headersIndex][key] = value;
}
return resultItem;
};
console.log(arrayOfObjects.map(toResultItem));
const arrayOfObjects = [
{ A: 1, B: 2, C: 3 },
{ A: 3, B: 4, C: 1 },
];
const headers = [['A', 'B'], ['C', 'D']];
const result = arrayOfObjects.map((obj) =>
headers.map((header) =>
header.reduce((acc, key) => {
acc[key] = obj[key];
return Object.keys(acc).reduce((newAcc, key) => {
if (acc[key]) {
newAcc[key] = acc[key];
}
return newAcc;
}
, {});
}, {})
)
);
console.log(result);
Array.forEach implementation
Logic
Loop through arrayOfObjects array.
Inside that, loop through headers array.
Inside that, loop through each array in the headers array.
Create an empty object and assign the property from nodes in headers array with values from objects in arrayOfObjects array.
const arrayOfObjects = [
{ A: 1, B: 2, C: 3 },
{ A: 3, B: 4, C: 1 }
];
const headers = [
['A', 'B'],
['C']
];
const baseArray = []
arrayOfObjects.forEach((obj) => {
const childNode = [];
headers.forEach((head) => {
const node = {};
head.forEach((key) => node[key] = obj[key]);
childNode.push(node);
});
baseArray.push(childNode);
});
console.log(baseArray)
Array.map and Array.reduce implementation.
Using the same logic implementes in the above solution, we can rewrite this using Array.map and Array.reduce as below.
const arrayOfObjects = [
{ A: 1, B: 2, C: 3 },
{ A: 3, B: 4, C: 1 }
];
const headers = [
['A', 'B'],
['C']
];
const output = arrayOfObjects.map((obj) => {
return headers.map((header) => {
return header.reduce((acc, curr) => {
acc[curr] = obj[curr];
return acc;
}, {});
})
})
console.log(output);
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);
}
};
Can I create an Array from an Object just in one line? I don't want all the values object, just a selection:
const myObject = { a: 'foo', b: 'bar', c:'yep' }
const { a, c } = myObject
const myArray = Array.of(a, c)
console.log(myArray)
Could I use destructuring in some way inside the Array.of parameter?
Why not just :
const myObject = { a: 'foo', b: 'bar', c:'yep' };
let arr = Array.of(myObject.a, myObject.c);
console.log(arr);
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'
});
Given input:
[{ a: 1 }, { b: 2 }, { c: 3 }]
How to return:
{ a: 1, b: 2, c: 3 }
For arrays it's not a problem with lodash but here we have array of objects.
Use Object.assign:
let merged = Object.assign(...arr); // ES6 (2015) syntax
var merged = Object.assign.apply(Object, arr); // ES5 syntax
Note that Object.assign is not yet implemented in many environment and you might need to polyfill it (either with core-js, another polyfill or using the polyfill on MDN).
You mentioned lodash, so it's worth pointing out it comes with a _.assign function for this purpose that does the same thing:
var merged = _.assign.apply(_, [{ a: 1 }, { b: 2 }, { c: 3 }]);
But I really recommend the new standard library way.
With lodash, you can use merge():
var arr = [ { a: 1 }, { b: 2 }, { c: 3 } ];
_.merge.apply(null, [{}].concat(arr));
// → { a: 1, b: 2, c: 3 }
If you're doing this in several places, you can make merge() a little more elegant by using partial() and spread():
var merge = _.spread(_.partial(_.merge, {}));
merge(arr);
// → { a: 1, b: 2, c: 3 }
Here is a version not using ES6 methods...
var arr = [{ a: 1 }, { b: 2 }, { c: 3 }];
var obj = {};
for(var i = 0; i < arr.length; i++) {
var o = arr[i];
for(var key in o) {
if(typeof o[key] != 'function'){
obj[key] = o[key];
}
}
}
console.log(obj);
fiddle: http://jsfiddle.net/yaw3wbb8/
You can use underscore.extend function like that:
var _ = require('underscore');
var a = [{ a: 1 }, { b: 2 }, { c: 3 }];
var result = _.extend.apply(null, a);
console.log(result); // { a: 1, b: 2, c: 3 }
console.log(a); // [ { a: 1, b: 2, c: 3 }, { b: 2 }, { c: 3 } ]
And to prevent modifying original array you should use
var _ = require('underscore');
var a = [{ a: 1 }, { b: 2 }, { c: 3 }];
var result = _.extend.apply(null, [{}].concat(a));
console.log(result); // { a: 1, b: 2, c: 3 }
console.log(a); // [ { a: 1 }, { b: 2 }, { c: 3 } ]
Here can test it
Adding to the accepted answer, a running code snippet with ES6.
let input = [{ a: 1 }, { b: 2 }, { c: 3 }]
//Get input object list with spread operator
console.log(...input)
//Get all elements in one object
console.log(Object.assign(...input))
I've got a neat little solution not requiring a polyfill.
var arr = [{ a: 1 }, { b: 2 }, { c: 3 }];
var object = {};
arr.map(function(obj){
var prop = Object.getOwnPropertyNames(obj);
object[prop] = obj[prop];
});
Hope that helps :)
Here is a nice usage of Object.assign with the array.prototype.reduce function:
let merged = arrOfObjs.reduce((accum, val) => {
Object.assign(accum, val);
return accum;
}, {})
This approach does not mutate the input array of objects, which could help you avoid difficult to troubleshoot problems.
With more modern spread operator
arrOfObj.reduce( (acc, curr) => ({ ...acc, ...cur }) );
You can easily flat your object to array.
function flatten(elements) {
return elements.reduce((result, current) => {
return result.concat(Array.isArray(current) ? flatten(current) : current);
}, []);
};
6 years after this question was asked.
Object.assign is the answer (above) I like the most.
but is this also legal ?
let res = {};
[{ a: 1 }, { b: 2 }, { c: 3 }].forEach(val => {
let key = Object.keys(val);
console.log(key[0]);
res[key] = val[key];
})
const data = [
[{ a: "a" }, { b: "b" }, { c: "c" }],
[{ d: "d" }, { e: "e" }, { f: "f" }],
[{ g: "g" }, { h: "h" }, { i: "i" }],
];
function convertToObject(array){
const response = {};
for (let i = 0; i < array.length; i++) {
const innerArray = array[i];
for (let i = 0; i < innerArray.length; i++) {
const object = innerArray[i];
const keys = Object.keys(object);
for (let j = 0; j < keys.length; j++) {
const key = keys[j];
response[key] = object[key];
}
}
}
return response;
}
console.log(convertToObject(data));
function carParts(manufacturer, model, ...parts) {
return { manufacturer, model, ...Object.assign(...parts) };
}
console.log(
carParts(
"Honda",
"2008",
{ color: "Halogen Lights" },
{ Gears: "Automatic Gears" },
{ LED: "Android LED" },
{ LED: "Android LED1" }
)
);
This is how i have done.