Transform structure of array of objects - javascript

I have data like -
var data = [{"DefaultZone":[{"key":"stream0","value":100},
{"key":"stream1","value":50},
{"key":"stream2","value":10}
]},
{"Zone 1":[{"key":"stream0","value":120},
{"key":"stream1","value":55},
{"key":"stream2","value":15}
]}
]
and wanted to transform it like -
var data = [{"key": "stream0", "values":[{"x":"DefaultZone","y":100}, {"x":"Zone 1","y":120}]},
{"key": "stream1", "values":[{"x":"DefaultZone","y":50}, {"x":"Zone 1","y":55}]},
{"key": "stream2", "values":[{"x":"DefaultZone","y":10}, {"x":"Zone 1","y":15}]}
];
using JavaScript(ES6). Any help would be highly appreciated..

Here is the first way that came to mind:
var data = [{
"DefaultZone": [
{ "key": "stream0", "value": 100 },
{ "key": "stream1", "value": 50 },
{ "key": "stream2", "value": 10 }]
}, {
"Zone 1": [
{ "key": "stream0", "value": 120 },
{ "key": "stream1", "value": 55 },
{ "key": "stream2", "value": 15 }]
}];
let working = data.reduce((p, c) => {
let x = Object.keys(c)[0];
c[x].forEach(v => {
if (!p[v.key]) p[v.key] = [];
p[v.key].push({ x: x, y: v.value });
});
return p;
}, {});
let output = Object.keys(working).map(v => ({ key: v, values: working[v] }));
console.log(output);
Further reading:
the array .reduce() method
the Object.keys() method
the array .forEach() method
the array .map() method

Although I like nnnnnn's answer, here is another one, using only the Object.keys() method:
var data = [{
"DefaultZone": [{
"key": "stream0",
"value": 100
}, {
"key": "stream1",
"value": 50
}, {
"key": "stream2",
"value": 10
}]
}, {
"Zone 1": [{
"key": "stream0",
"value": 120
}, {
"key": "stream1",
"value": 55
}, {
"key": "stream2",
"value": 15
}]
}]
final = {}
data.forEach(function(x) {
Object.keys(x).forEach(function(y) {
x[y].forEach(function(z) {
if (!final[z['key']]) final[z['key']] = [];
final[z['key']].push({
'x': y,
'y': z['value']
})
})
})
})
answer = []
Object.keys(final).forEach(function(x) {
answer.push({
'key': x,
values: final[x]
})
})
console.log(answer)

Related

How to group together objects in an array with the same numerical value?

I have an array of objects like so:
arrayOfObjects = [
{
"name": "OneFullValue",
"value": 709
},
{
"name": "DRTG",
"value": 0
},
{
"name": "OtherFullValue",
"value": 345
},
{
"name": "TYU",
"value": 0
},
{
"name": "TRHY",
"value": 0
},
{
"name": "UOI",
"value": 0
},
]
End goal:
arrayOfObjectsEndGoal = [
{
"name": "OneFullValue",
"value": 709
},
{
"name": "DRTG - TYU - TRHY - UOI",
"value": 0
},
{
"name": "OtherFullValue",
"value": 345
}
]
Essentially, I want to group together all of the objects with the same value where the "name" key has the value of all of the names of the other objects separated by a -.
NOTE: THE VALUE CAN BE ANY NUMBER OTHER THAN 0, FOR EXAMPLE, IF I HAVE AN ARRAY LIKE SO:
arrayOfObjects = [
{
"name": "OneFullValue",
"value": 709
},
{
"name": "DRTG",
"value": 123
},
{
"name": "OtherFullValue",
"value": 345
},
{
"name": "TYU",
"value": 123
},
{
"name": "TRHY",
"value": 123
},
{
"name": "UOI",
"value": 123
},
]
End goal (we're not multiplying 123 by how many objects there are with value 123, we're just equating it):
arrayOfObjectsEndGoal = [
{
"name": "OneFullValue",
"value": 709
},
{
"name": "DRTG - TYU - TRHY - UOI",
"value": 123
},
{
"name": "OtherFullValue",
"value": 345
}
]
I know how to combine all of the objects together
arrayOfObjects.reduce(
((prev, oth) => Object.assign(prev, oth)), {}
)
I also know that I can use a foreach to loop through the array and manipulate the values:
let objItem = {};
let arrayOfObjectsEndGoal = [];
arrayOfObjects.foreach((obj) => {
if (objItem[obj.value]) {
let first = objItem[obj.name] -1;
let newValue = {
...arrayOfObjectsEndGoal[first]
};
arrayOfObjectsEndGoal[first] = newValue;
});
However, I'm unsure of how to move forwards to achieve the result. How can I combine objects like above?
You could add the names.
const
data = [{ name: "OneFullValue", value: 709 }, { name: "DRTG", value: 0 }, { name: "OtherFullValue", value: 345 }, { name: "TYU", value: 0 }, { name: "TRHY", value: 0 }, { name: "UOI", value: 0 }],
result = Object.values(data.reduce((r, { name, value }) => {
r[value] ??= { name: '', value };
r[value].name += (r[value].name && ' - ') + name;
return r;
}, {}));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

how to change the format of json array by loping over

Hi I am getting data from API but I want my data in different format so that I can pass later into a function. I want to change the names of keys into a different one becasuse I have created a chart and it only draws if I send it data in certain way
This is what I am getting from API
data = {
"status": "success",
"from": "DB",
"indice": "KSE100",
"data": [
{
"stock_sector_name": "Tc",
"sector_score": "0828",
"stocks": [
{
"stock_symbol": "TRG",
"stock_score": 44
},
{
"stock_symbol": "SYS",
"stock_score": 33
}
]
},
{
"stock_sector_name": "OIL",
"sector_score": "0828",
"stocks": [
{
"stock_symbol": "FFS",
"stock_score": 44
},
{
"stock_symbol": "SMS",
"stock_score": 33
}
]
},
]
}
But I want my data to look like this like this
data = {
"name": "KSE100",
"children": [
{
"name": "A",
'points': -9,
"children": [
{
"stock_title": "A",
"value": 12,
},
{
"stock_title": "B",
"value": 4,
},
]
},
{
"name": "B",
'points': 20,
"children": [
{
"stock_title": "A",
"value": 12,
},
{
"name": "B",
"value": 4,
},
]
},
]
}
Like I want to replace
stock_sector_name = name
sector_score = value
stocks = children
stock_symbol = name
stock_score = value
I have been trying this for so much time but sill could not figured it out
function convert(d){
return {
name : d.indice,
children : d.data.map(y=>{
return {
name : y.stock_sector_name,
points : y.sector_score,
children : y.stocks.map(z=>{
return {
stock_title: z.stock_symbol,
value : z.stock_score
}
})
}
})
}
}
You can do something like this
const data = {
"status": "success",
"from": "DB",
"indice": "KSE100",
"data": [{
"stock_sector_name": "Tc",
"sector_score": "0828",
"stocks": [{
"stock_symbol": "TRG",
"stock_score": 44
},
{
"stock_symbol": "SYS",
"stock_score": 33
}
]
},
{
"stock_sector_name": "OIL",
"sector_score": "0828",
"stocks": [{
"stock_symbol": "FFS",
"stock_score": 44
},
{
"stock_symbol": "SMS",
"stock_score": 33
}
]
},
]
}
const data2 = {
"name": "KSE100",
"children": [{
"name": "A",
'points': -9,
"children": [{
"stock_title": "A",
"value": 12,
},
{
"stock_title": "B",
"value": 4,
},
]
},
{
"name": "B",
'points': 20,
"children": [{
"stock_title": "A",
"value": 12,
},
{
"name": "B",
"value": 4,
},
]
},
]
}
//stock_sector_name = name
//sector_score = value
//stocks = children
//stock_symbol = stock_title
//stock_score = value
const keys = {
stock_sector_name: "name",
sector_score: "points",
stocks: "children",
stock_symbol: "stock_title",
stock_score: "value",
indice: "name",
//data: "children"
}
const rename = (value) => {
if (!value || typeof value !== 'object') return value;
if (Array.isArray(value)) return value.map(rename);
return Object.fromEntries(Object
.entries(value)
.map(([k, v]) => [keys[k] || k, rename(v)])
);
}
renamedObj = rename(data);
console.log(renamedObj);

Count key values from a nested object array

I have an array like this:
[
{
"costs": [{
"value": "80"
}],
"id": 4,
"name": "Subscription Fee",
"month": "March"
},
[
{
"costs": [{
"value": "200"
}],
"id": 2,
"name": "Tution",
"month": "March"
},
{
"costs": [{
"value": "10"
}],
"id": 11,
"name": "DEMO"
}
]
]
I need to have sumation of all the values from costs. How can i do that?
const data = [
{"costs":[{"value":"80"}],"id":4,"name":"Subscription Fee","month":"March"},
[
{"costs":[{"value":"200"}],"id":2,"name":"Tution","month":"March"},
{"costs":[{"value":"10"}],"id":11,"name":"DEMO"}
]
];
// flatten the arrays to get a list of objects
// iterate over this list
const res = data.flat().reduce((total, { costs = [] }) => {
// add the values of this item's costs with total
costs.forEach(({ value = 0 }) => total += +value);
return total;
}, 0);
console.log(res);

node js create an object in specific pattern from array of object

I'm facing some issue in for loop while creating an object from array of object.I have an array as this in node js app:
[
{
"Material": "113/133",
"Name": [
{
"name": "WELD1",
"value": 27520
},
{
"name": "WELD2",
"value": 676992
},
{
"name": "WELD3",
"value": 421
}
]
},
{
"Material": "150/300",
"Name": [
{
"name": "WELD1",
"value": 1441
},
{
"name": "WELD2",
"value": 555
},
{
"name": "WELD3",
"value": 100992
}
]
}
]
I want to return object like this which contains all the Material as array, Name and there value in array of object like this:
{
Material: ["113/133", "150/300"],
datasets: [
{
label: "WELD1",
data: [27520,1441]
},
{
label: "WELD2",
data: [676992,555]
},
{
label: "WELD3",
data: [100,20,0]
}
]
}
I want to get result using for loop.
you can use .reduce() and do something like this:
var arr = [
{
"Material": "113/133",
"Name": [
{
"name": "WELD1",
"value": 27520
},
{
"name": "WELD2",
"value": 676992
},
{
"name": "WELD3",
"value": 421
}
]
},
{
"Material": "150/300",
"Name": [
{
"name": "WELD1",
"value": 1441
},
{
"name": "WELD2",
"value": 555
},
{
"name": "WELD3",
"value": 100992
}
]
}
];
var newArr = arr.reduce((acc, ob) => {
for (var key in ob)
if(typeof acc[key] === 'object')
acc[key] = acc[key] ? acc[key].concat(ob[key]) : [ob[key]];
else
acc[key] ? acc[key].push(ob[key]) : acc[key] = [ob[key]];
return acc;
}, {});
console.log(newArr);
let array = [
{
"Material": "113/133",
"Name": [
{
"name": "WELD1",
"value": 27520
},
{
"name": "WELD2",
"value": 676992
},
{
"name": "WELD3",
"value": 421
}
]
},
{
"Material": "150/300",
"Name": [
{
"name": "WELD1",
"value": 1441
},
{
"name": "WELD2",
"value": 555
},
{
"name": "WELD3",
"value": 100992
}
]
}
]
let answer = {Material: [], datasets: []}
array.forEach(x => {
answer.Material.push(x.Material);
x.Name.forEach(na => {
let object = answer.datasets.find(obj => obj.label === na.name) || {label: "", data: []};
if(object.label === ""){
object.label = na.name;
object.data.push(na.value);
answer.datasets.push(object);
}else{
object.data.push(na.value)
}
});
});
console.log(answer);
The above is alternative solution using forEach instead of reduce
Use of Array.reduce to build your new data structure using data you have
const start = [{
"Material": "113/133",
"Name": [{
"name": "WELD1",
"value": 27520
},
{
"name": "WELD2",
"value": 676992
},
{
"name": "WELD3",
"value": 421
}
]
},
{
"Material": "150/300",
"Name": [{
"name": "WELD1",
"value": 1441
},
{
"name": "WELD2",
"value": 555
},
{
"name": "WELD3",
"value": 100992
}
]
}
];
const end = start.reduce((tmp, {
Material,
Name,
}) => {
// Handle the material
// If it do not exist in the array, push it
if (!tmp.Material.includes(Material)) {
tmp.Material.push(Material);
}
// Handle the datasets
// Look at each Name
Name.forEach(({
name,
value,
}) => {
// Can we find the label?
const labelFind = tmp.datasets.find(y => y.label === name);
// If we can't find the label, create a new dataset
if (!labelFind) {
tmp.datasets.push({
label: name,
data: [
value,
],
});
return;
}
// If we has found it push new value in the dataset
labelFind.data.push(value);
});
return tmp;
}, {
Material: [],
datasets: [],
});
console.log(end);
// This is the old fashioned way.
// Iterate over whole array,
// make a map, push value where 'name' is found in map
// later iterate over this map - dataMap - and form required datasets array.
var Material = [];
var dataMap = {};
arr.forEach(obj => {
Material.push(obj.Material);
obj.Name.forEach(item => {
if(dataMap[item.name]){
dataMap[item.name].push(item.value);
}
else {
dataMap[item.name] = [item.value];
}
});
});
var datasets = [];
Object.keys(dataMap).forEach(label => {
datasets.push({
label: label,
data: dataMap[label]
});
});
var result = {
Material: Material,
datasets: datasets
}
console.log(result);

d3 Grouping data on multiple values in combination with key value pair

I collect some json data. The actions on this data what i want to accomplished with d3js is the following:
Group data on the following json key's: "date" and "name"
Count the records wich match the above json keys
Return the result in a key value pair
JSON DATA
var expenses = [{"name":"jim","amount":34,"date":"11/12/2015"},
{"name":"carl","amount":120.11,"date":"11/12/2015"},
{"name":"jim","amount":45,"date":"12/01/2015"},
{"name":"stacy","amount":12.00,"date":"01/04/2016"},
{"name":"stacy","amount":34.10,"date":"01/04/2016"},
{"name":"stacy","amount":44.80,"date":"01/05/2016"}
];
I tried according the ( http://learnjsdata.com/group_data.html ) the following script:
var expensesTotalByDay = d3.nest()
.key(function(d) { return d.name; })
.key(function(d) { return d.date; })
.rollup(function(v) { return d3.sum(v, function(d) { return d.amount; }); })
.map(expenses);
But this results in:
{"jim":{"11/12/2015":34,"12/01/2015":45},
"carl":{"11/12/2015":120.11},
"stacy":{"01/04/2016":46.1,"01/05/2016":44.8}}
instead of(the expected result): EDITED 21:33
[
{
key: "jim", value:[
{
"key": "11/12/2015",
"value": 34
},
{
"key": "12/01/2015",
"value": 45
}
]
},
{
key: "carl", value:[
{
"key": "11/12/2015",
"value": 120.11
}
]
},
{
key: "stacy", value: [
{
"key": "01/04/2016",
"value": 12
},
{
"key": "01/04/2016",
"value": 34.1
},
{
"key": "01/05/2016",
"value": 44.8
}
]
}
]
I hope you can help me solve this issue.
Manny thanks
Erik
A proposal in plain Javascript with Array#forEach and a helper object.
var expenses = [{ "name": "jim", "amount": 34, "date": "11/12/2015" }, { "name": "carl", "amount": 120.11, "date": "11/12/2015" }, { "name": "jim", "amount": 45, "date": "12/01/2015" }, { "name": "stacy", "amount": 12.00, "date": "01/04/2016" }, { "name": "stacy", "amount": 34.10, "date": "01/04/2016" }, { "name": "stacy", "amount": 44.80, "date": "01/05/2016" }],
result = [];
expenses.forEach(function (a) {
if (!this[a.name]) {
this[a.name] = { key: a.name, value: [] };
result.push(this[a.name]);
}
this[a.name].value.push({ key: a.date, value: a.amount });
}, Object.create(null));
document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');

Categories