javascript cannot map array of objects with nested values - javascript

Trying to map array of objects with values nested in child objects structure like:
const objs = [{
"B": {
"value": 1,
},
"D": {
"value": "45"
},
"E": {
"value": "234"
},
"A": {
"value": "543"
},
"C": {
"value": "250"
}
},...]
to the structure like:
[
{ name: 'B', value: 1 },
{ name: 'D', value: '45' },
{ name: 'E', value: '234' },
{ name: 'A', value: '543' },
{ name: 'C', value: '250' }
]
and the result of the mapping is undefined
const mapped = objs.map((key, index) => {
Object.keys(key).map(el => ({
name: el
}))
})
Example: Stackblitz

You are missing return statement and value property definition.
Besides you may want to use flatMap instead of map in order to avoid a nested array in the result:
const objs = [{
"B": {
"value": 1,
},
"D": {
"value": "45"
},
"E": {
"value": "234"
},
"A": {
"value": "543"
},
"C": {
"value": "250"
}
}]
const mapped = objs.flatMap((key, index) => {
return Object.keys(key).map(el => ({
name: el,
value: key[el].value
}))
})
console.log(mapped)

You should operate on objs[0], not objs, because it is an array of one object, not array of objects.
let array = []
for(let object in objs[0]){
array.push({
"name": object,
"value": objs[0][object].value
})
}

return is missing in Object.keys. As well instead of Object.keys use Object.entries to get key and value.
const objs = [{
"B": {
"value": 1,
},
"D": {
"value": "45"
},
"E": {
"value": "234"
},
"A": {
"value": "543"
},
"C": {
"value": "250"
}
}];
const mapped = objs.map((key, _) => {
return Object.entries((key)).map(([name, {
value
}]) => ({
name,
value
}))
}).flat();
console.log(mapped);

Related

How to .map correctly this array of objects?

I'm not sure what I'm doing wrong but I would like to map an array of objects. This array of objects it's dynamic, this means sometimes it has 4 objects and sometimes 20, so I need to make sure it will work no matters how many entries it has:
var obj = [
{
"key": "one",
"value": "something"
},
{
"key": "two",
"value": "random"
},
{
"key": "blue",
"value": "chicken"
},
{
"key": "orange",
"value": "sportsman"
}
];
I need to pass this objects into one to send it through a POST call that should match this format:
form: {
'one': 'something',
'two': 'random',
'blue': 'chicken',
'orange': 'sportsman'
}
I can access to item.value but IDK why I can't item.key:
var obj = [
{
"key": "one",
"value": "something"
},
{
"key": "two",
"value": "random"
},
{
"key": "blue",
"value": "chicken"
},
{
"key": "orange",
"value": "sportsman"
}
];
var combined = obj.map(function combined(item) {
return {
item.key: item.value
};
})
console.log(combined);
Any ideas? Thanks.
You shouldn't return an object from your callback function. Return an array of the key and value, then use Object.fromEntries() to turn this into a single object with those keys and values.
var obj = [{
"key": "one",
"value": "something"
},
{
"key": "two",
"value": "random"
},
{
"key": "blue",
"value": "chicken"
},
{
"key": "orange",
"value": "sportsman"
}
];
var combined = Object.fromEntries(obj.map(item => [item.key, item.value]));
console.log(combined);
1) You can't use a map here because the map will return a new array. You can achieve this result using reduce
var obj = [
{
key: "one",
value: "something",
},
{
key: "two",
value: "random",
},
{
key: "blue",
value: "chicken",
},
{
key: "orange",
value: "sportsman",
},
];
const result = obj.reduce((acc, curr) => {
const { key, value } = curr;
acc[key] = value;
return acc;
}, {});
console.log(result);
2) You can also do this using for..of loop
var obj = [{
key: "one",
value: "something",
},
{
key: "two",
value: "random",
},
{
key: "blue",
value: "chicken",
},
{
key: "orange",
value: "sportsman",
},
];
const result = {};
for (let o of obj) {
result[o.key] = o.value;
}
console.log(result);

Converting parent / children structure to object

I need to convert js object like this:
{
"id": 1,
"name": "A",
"parent": null,
"children": [
{
"id": 2,
"name": "B",
"parent": 1,
"children": []
},
{
"id": 3,
"name": "C",
"parent": 1,
"children": [
{
"id": 4,
"name": "D",
"parent": 3,
"children": []
}
]
}
]
}
to another like this:
{
"А": [
{
"B": "value",
"C": [
{
"D": "value"
}
]
}
]
}
I wrote the function, but it returns the wrong object with several nested arrays:
const convert = (obj) => {
return obj.map((i) => {
return Object.keys(i).filter(y => y === 'name').map(key => {
return i['children'].length > 0 ? { [i[key]]: convert(i['children']) } : { [i[key]]: 'value' }
});
})
};
How to change my implementation for getting the right object?
You could build the entries from objects and map nested children, if exists.
const
transform = array => Object.fromEntries(array.map(({ name, children }) =>
[name, children.length ? [transform(children)] : 'value']
)),
data = { id: 1, name: "A", parent: null, children: [{ id: 2, name: "B", parent: 1, children: [] }, { id: 3, name: "C", parent: 1, children: [{ id: 4, name: "D", parent: 3, children: [] }] }] },
result = transform([data]);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Group an array of objects based on a specific field

I have an array of objects. I want to group them by a specific field.
[
{
"name": "JOHN",
"type": 1,
"sum": 5
},
{
"name": "SERA",
"type": 1,
"sum": 43
},
{
"name": "SERA",
"type": 2,
"sum": 129
},
{
"name": "JOHN",
"type": 2,
"sum": 200
}
]
The output I expect for grouping by name attribute is as follows.
{
// Group #1
"JOHN": [
{
"type": 2,
"sum": 200
}
{
"type": 1,
"sum": 5
}
],
// Group #2
"SERA":[
{
"type": 1,
"sum": 43
},
{
"type": 2,
"sum": 129
},
]
}
I used nested loops, but unfortunately the execution speed was slow and it did not give the right results.
As if you mentioned, we can use an object instead of an array for the most outer wrapper. And also swap inside one object to an array, then this is a possible solution.
var data = [{"name": "JOHN","type": 1,"sum": 5},{"name": "SERA","type": 1,"sum": 43},{"name": "SERA","type": 2,"sum": 129},{"name": "JOHN","type": 2,"sum": 200}];
var newData = {};
data.forEach( (item) => {
if (!(item['name'] in newData)) {
newData[item['name']] = [];
}
newData[item['name']].push(
{
'type': item['type'],
'sum' : item['sum']
}
);
});
console.log(newData);
Your proposed output structure is not valid, however using Array.reduce you can create an object in which all the properties are arrays of objects:
const data = [
{
"name": "JOHN",
"type": 1,
"sum": 5
},
{
"name": "SERA",
"type": 1,
"sum": 43
},
{
"name": "SERA",
"type": 2,
"sum": 129
},
{
"name": "JOHN",
"type": 2,
"sum": 200
}
];
const result = data.reduce((c, {name, type, sum}) => {
c[name] = c[name] || [];
c[name].push({type, sum});
return c;
}, {});
console.log(result);
One more way with forEach, destructuring and ?? operator
const merge = (arr) => {
const obj = {};
arr.forEach(({ name, ...rest }) => (obj[name] ??= []).push(rest));
return obj;
};
const data = [
{
name: "JOHN",
type: 1,
sum: 5,
},
{
name: "SERA",
type: 1,
sum: 43,
},
{
name: "SERA",
type: 2,
sum: 129,
},
{
name: "JOHN",
type: 2,
sum: 200,
},
];
console.log(merge(data));
You can use this function which take advantage of Array.prototype.reduce to transform the initial data to another structure of array.
let data = [
{
"name": "JOHN",
"type": 1,
"sum": 5
},
{
"name": "SERA",
"type": 1,
"sum": 43
},
{
"name": "SERA",
"type": 2,
"sum": 129
},
{
"name": "JOHN",
"type": 2,
"sum": 200
}
];
function groupedBy(data, field) {
let fieldValues = [...data].reduce((acc, current) => {
return acc.concat(current[field]);
}, []).filter((value, index, self) => {
return self.indexOf(value) === index;
});
let results = fieldValues.reduce((acc, item) => {
let items = [...data].filter(el => {
return el.name === item;
});
items.forEach(i => delete i.name);
return Object.assign(acc, { [item]: items});
}, {});
return results;
}
console.log(groupedBy(data, "name"));

Angular 6 merge two array to count the length of key

I have an array of two objects which has another array of objects, i want the count of all objects of property "value" in the following sample.
var data = [
{
"x": "123",
"values": [
{
"a": "1"
},
{
"b": "2"
}
]
}, {
"y": "123",
"values": [
{
"a": "1"
},
{
"b": "2"
}
]
}
];
I have used the following logic :-
let _data = data.RESULT;
console.log(JSON.stringify(_data));
_data.forEach(element => {
this.someObj = element;
});
The expected result should be the length of values property, i.e. 4
If you want to find only length of "values" array then you need to do this
data = [
{
"x": "123",
"values": [
{
"a": "1"
},
{
"b": "2"
}
]
}, {
"y": "123",
"values": [
{
"a": "1"
},
{
"b": "2"
}
]
}
]
length = 0;
constructor() {
this.data.forEach((d) => {
length = length + d.values.length;
});
console.log('length', length);
}
https://stackblitz.com/edit/angular-3daqcy?file=src%2Fapp%2Fapp.component.ts
Created a function that adds the lengths of the values array
var arr = [
{
"x": "123",
"values": [
{
"a": "1"
},
{
"b": "2"
}
]
}, {
"y": "123",
"values": [
{
"a": "1"
},
{
"b": "2"
}
]
}
]
function getKeysLength(arr){
var count = 0;
arr.forEach((val)=>{count= count+ val.values.length})
return count
}
var ans = getKeysLength(arr);
console.log("ans",ans);
If you want to do it in a single line then you can do it with map and reduce,map creates a new array with the elements as the length of the values property and reduce calculates the sum of the new array elements . Which gives you the sum of the length of all values property arrays.
Here is the code below -
let data = [
{
"x": "123",
"values": [
{
"a": "1"
},
{
"b": "2"
}
]
}, {
"y": "123",
"values": [
{
"a": "1"
},
{
"b": "2"
}
]
}
];
let totalLength = data.map(x => x.values.length).reduce((a,b) => a+b,0);
console.log(temparr);
Here is a working Stackblitz with Angular 6
https://stackblitz.com/edit/hello-angular-6-ewa5tb?file=src/app/app.component.ts

Reformat an object

I have the following:
{
"SOL": {
"B": [
"ABC",
"DEF"
],
"C": [
"JKL",
"MNO"
]
}
}
I'd like it to read:
{
"SOL": [
{
"id": "B",
"states": [
{
"id": "ABC"
},
{
"id": "DEF"
]
},
{
"id": "C",
"states": [
{
"id": "JKL"
},
{
"id": "MNO"
}
]
}
]
}
I've managed to give an "id" key to the 2nd level but I can't figure out how to add one to each of the states - how can I do that?
Code:
object.SOL = Object.keys(object.SOL).map(function (k) {
return { id: k, states: object.SOL[k] };
})
Here's a fiddle
You can just use another map inside to remap the states to objects:
object.SOL = Object.keys(object.SOL).map(function (k) {
return {
id: k,
states: object.SOL[k].map(function(i){
return {id: i };
})
}
});
Updated fiddle: https://jsfiddle.net/ouybL99u/2/
object.SOL = Object.keys(object.SOL).map(function (k) {
return { id: k, states: object.SOL[k].map(function(kk){ return {id:kk} }) };
})

Categories