Convert json response to table - javascript

I'm trying to convert json response to array which accepts my table (component from devextreme). I'm trying to do that on angular 6. Json looks like that:
"data": [
{
"type": "A",
"date": "2018-05",
"value": "153"
},
{
"type": "B",
"date": "2018-05",
"value": "888"
},
{
"type": "C",
"date": "2018-05",
"value": "999"
},
{
"type": "D",
"date": "2018-05",
"value": "555"
},
{
"type": "A",
"date": "2018-06",
"value": "148"
},
{
"type": "B",
"date": "2018-06",
"value": "222"
},
{
"type": "C",
"date": "2018-06",
"value": "555"
},
{
"type": "D",
"date": "2018-06",
"value": "666"
},
{
"type": "A",
"date": "2018-07",
"value": "156"
},
{
"type": "B",
"date": "2018-07",
"value": "111"
},
{
"type": "C",
"date": "2018-07",
"value": "333"
},
{
"type": "D",
"date": "2018-07",
"value": "999"
}
],
"number": "111-111"
}
]
And I need to transform it to this format:
[{
month: '2018-05',
A: 153,
B: 888,
C: 999,
D: 555
},
{
month: '2018-06',
A: 148,
B: 222,
C: 555,
D: 666
},
{
month: '2018-07',
A: 156,
B: 111,
C: 333,
D: 999
}]
Number of types can change (so there could be A and B only for example). Can anybody help me with that ? I'm using this component to present data at website https://js.devexpress.com/Demos/WidgetsGallery/Demo/DataGrid/SimpleArray/Angular/Light/

This is how I would approach your problem:
1) Get the list of types and dates from your data source. We make use of JavaScript's Set to store the values so that the values will be unique (without duplicates).
The value from date will be considered as the unique key for each object in the result array, and the type will be the other properties of the result ('A', 'B', 'C', and 'D')
2) Once we have those 2 arrays, we will iterate through the original list to generate the object. The values of properties A, B, C, D are populated by filtering the date and type from the original list.
const list = {"data":[{"type":"A","date":"2018-05","value":"153"},{"type":"B","date":"2018-05","value":"888"},{"type":"C","date":"2018-05","value":"999"},{"type":"D","date":"2018-05","value":"555"},{"type":"A","date":"2018-06","value":"148"},{"type":"B","date":"2018-06","value":"222"},{"type":"C","date":"2018-06","value":"555"},{"type":"D","date":"2018-06","value":"666"},{"type":"A","date":"2018-07","value":"156"},{"type":"B","date":"2018-07","value":"111"},{"type":"C","date":"2018-07","value":"333"},{"type":"D","date":"2018-07","value":"999"}],"number":"111-111"};
// const dates = [...new Set(list.data.map(item => item.date))];
const dates = Array.from(list.data.map(item => item.date));
console.log(dates);
// const types = [...new Set(list.data.map(item => item.type))];
const types = Array.from(list.data.map(item => item.type));
console.log(types)
const res = dates.map(date => {
const obj = {};
types.map(type => {
obj[type] = list.data.filter(item => item.date === date && item.type === type)[0].value;
});
obj.date = date;
return obj;
});
console.log(res);

Given that your input is
let input = {
"data": [
{
"type": "A",
"date": "2018-05",
"value": "153"
},
{
"type": "B",
"date": "2018-05",
"value": "888"
},
{
"type": "C",
"date": "2018-05",
"value": "999"
},
{
"type": "D",
"date": "2018-05",
"value": "555"
},
{
"type": "A",
"date": "2018-06",
"value": "148"
},
{
"type": "B",
"date": "2018-06",
"value": "222"
},
{
"type": "C",
"date": "2018-06",
"value": "555"
},
{
"type": "D",
"date": "2018-06",
"value": "666"
},
{
"type": "A",
"date": "2018-07",
"value": "156"
},
{
"type": "B",
"date": "2018-07",
"value": "111"
},
{
"type": "C",
"date": "2018-07",
"value": "333"
},
{
"type": "D",
"date": "2018-07",
"value": "999"
}
],
"number": "111-111"
};
You can do this to get the required result in the output variable
let output = [];
input.data.forEach(function (item) {
const type = item.type;
const date = item.date;
const value = item.value;
let newlyCreated = false;
let objForMonth = output.find(x => x.month == date);
if (!objForMonth) {
newlyCreated = true;
objForMonth = {};
objForMonth.month = date;
}
objForMonth[type] = value;
if (newlyCreated) {
output.push(objForMonth);
} else {
let indexToWriteTo = output.findIndex(x => x.month == date);
output[indexToWriteTo] = objForMonth;
}
});

You can try like this
TS
let finalArray = [];
let valueA: string = null;
let valueB: string = null;
let valueC: string = null;
// Here data is a variable which contain your JSON data
for(let i = 0; i < data.length; i++) {
if (data.type === 'A') {
valueA = data[i].value;
}
if (data.type === 'B') {
valueB = data[i].value;
}
if (data.type === 'C') {
valueC = data[i].value;
}
if (data.type === 'D') {
finalArray.push({
month: data[i].date
A: valueA,
B: valueB,
C: valueC,
D: data[i].value
});
}
}
console.log(finalArray);
Let me know if it is working or not.

Related

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);

Object.assign() for replacing objects of a json

I have JSON looks like this:
{
"ArrayInfo": [
{
"name": "A",
"Id": "1"
},
{
"name": "B",
"Id": "2"
},
{
"name": "C",
"Id": "3"
},
{
"name": "D",
"Id": "4"
}
]
}
I want to replace an object of JSON with another object.For example I have this object :
{"name":"E","Id":"5"}
and it is going to be replaced by this object of JSON:
{"name":"B","Id":"2"}
JSON should look like this :
{
"ArrayInfo": [
{
"name": "A",
"Id": "1"
},
{
"name": "E",
"Id": "5"
},
{
"name": "C",
"Id": "3"
},
{
"name": "D",
"Id": "4"
}
]
}
What I did is to use Object.assign but the new object will be added to array instead of replacing.
(all the data is going to be dynamic but for making more understandable I use static data)
const itemToReplace = { "name": "E", "Id": "5" };
const prevItem = ArrayInfo[2]
ArrayInfo = ArrayInfo.map((el, idx) => {
return Object.assign({}, el, { prevItem: itemToReplace });
});
let NewArryInfo = ArrayInfo
console.log(NewArryInfo)
The result of console.log(NewArryInfo) :
{
"ArrayInfo": [
{
"name": "A",
"Id": "1"
},
{
"name": "B",
"Id": "2"
},
{
"name": "C",
"Id": "3"
},
{
"name": "D",
"Id": "4"
}
{
"name": "E",
"Id": "5"
}
]
}
You can use Array.prototype.splice to replace an item in Array.
const replaceItem = {"name":"E","Id":"5"}
const ArrayInfo = [
{
"name": "A",
"Id": "1"
},
{
"name": "B",
"Id": "2"
},
{
"name": "C",
"Id": "3"
},
{
"name": "D",
"Id": "4"
}
];
ArrayInfo.splice(1, 1, replaceItem); // remove second item and replace
console.log(ArrayInfo);
const object = {
"ArrayInfo": [{
"name": "A",
"Id": "1"
},
{
"name": "B",
"Id": "2"
},
{
"name": "C",
"Id": "3"
},
{
"name": "D",
"Id": "4"
}
]
};
const objectToReplace = {
"name": "B",
"Id": "2"
};
const updatedObject = Object.assign({}, object, {
ArrayInfo: object.ArrayInfo.map((info) => {
if (info.Id === objectToReplace.Id && info.name === objectToReplace.name) {
return {
"name": "E",
"Id": "5"
};
}
return info;
})
});
console.log(updatedObject);
const myArr = [
{
"name": "A",
"Id": "1"
},
{
"name": "B",
"Id": "2"
},
{
"name": "C",
"Id": "3"
},
{
"name": "D",
"Id": "4"
}
];
const replaceObj = (arr, objReplaced, objToReplaceWith) => {
const replacedObjIndex = arr.findIndex(item => JSON.stringify(item) === JSON.stringify(objReplaced));
arr[replacedObjIndex] = objToReplaceWith;
console.log(arr)
return arr;
}
replaceObj(myArr, {"name":"B","Id":"2"}, {"name":"E","Id":"5"});
In this way you can replace any object, from any position in the array.
You won't have to worry about the position of the item that you want to replace in the array and also you won't need to worry about it's keys or values.
When you map over the array you could check if each item is the one you want to replace, and if it is, return the new item instead.
ArrayInfo = ArrayInfo.map((el, idx) => {
if (el.id === prevItem.id && el.name === prevItem.name) {
return itemToReplace;
}
return el;
});
Try this!
let ArrayInfo = [{"name": "A","Id": "1"},{"name": "B","Id": "2"},{"name": "C","Id": "3"},{"name": "D","Id": "4"}];
const onReplace = {"name":"E","Id":"5"};
const toReplace = {"name": "B","Id": "2"};
function replaceArray(array, onReplace, toReplace) {
const removeIndex = array.map(item => { return item.name; }).indexOf(toReplace.name);
array.splice(removeIndex, removeIndex, onReplace);
return array
}
console.log(replaceArray(ArrayInfo, onReplace, toReplace));

How to calculate sum of count of array elements of multiple arrays by order and limit?

I have 3 arrays of 3 different types. Each array contains the count of an id (which might be duplicate like arrayOfB).
Each id has a limit value of count property is 10 (the count includes different types. Ex: if unique1 has 10 counts in type A, when process type B for unique1, it will be not processed).
const arrayOfA = [
{
"type": "A", "count": 10, "id": "UID1"
},
{
"type": "A", "count": 20, "id": "UID2"
},
{
"type": "A", "count": 1, "id": "UID4"
},
];
const arrayOfB = [
{
"type": "B", "count": 5, "id": "UID1"
},
{
"type": "B", "count": 5, "id": "UID3"
},
];
const arrayOfC = [
{
"type": "C", "count": 6, "id": "UID1"
},
{
"type": "C", "count": 6, "id": "UID4"
},
{
"type": "C", "count": 3, "id": "UID2"
},
{
"type": "C", "count": 3, "id": "UID3"
},
]
The output will be like:
Map {
'UID1|A' => 10,
'UID2|A' => 10,
'UID4|A' => 1,
'UID3|B' => 5,
'UID4|C' => 6 }
I used a set to hold id, which already has the maximum count and map to hold the output.
const maxed = new Set();
const elements = new Map();
arrayOfA.forEach(element => {
if (element.count > 10) {
maxed.add(`${element.id}`);
elements.set(`${element.id}|${element.type}`, 10);
console.log(elements)
return;
}
if (elements.has(`${element.id}|${element.type}`)) {
const newCount = elements.get(`${element.id}|${element.type}`) + element.count;
newCount > 10 ? elements.set(`${element.id}|${element.type}`, 10) : elements.set(`${element.id}|${element.type}`, newCount);
console.log(elements)
return;
}
elements.set(`${element.id}|${element.type}`, element.count);
});
arrayOfB.forEach(element => {
if (maxed.has(`${element.id}`)) {
console.log(elements)
return;
}
const countOfA = elements.has(`${element.id}|A`) ? elements.get(`${element.id}|A`) : 0;
let newCount = countOfA + element.count;
if (elements.has(`${element.id}|${element.type}`)) {
newCount = newCount + element.get(`${element.id}|${element.type}`);
}
if (newCount > 10) {
maxed.add(`${element.id}`);
if ((10 - countOfA) > 0) elements.set(`${element.id}|${element.type}`, 10 - countOfA);
console.log(elements)
return;
}
elements.set(`${element.id}|${element.type}`, element.count);
})
arrayOfC.forEach(element => {
if (maxed.has(`${element.id}`)) {
console.log(elements)
return;
}
const countOfA = elements.has(`${element.id}|A`) ? elements.get(`${element.id}|A`) : 0
const countOfB = elements.has(`${element.id}|C`) ? elements.get(`${element.id}|C`) : 0
let newCount = countOfA + countOfB + element.count;
if (elements.has(`${element.id}|${element.type}`)) {
newCount = newCount + element.get(`${element.id}|${element.type}`);
}
if (newCount > 10) {
maxed.add(`${element.id}`);
if ((10 - countOfA - countOfB) > 0); elements.set(`${element.id}|${element.type}`, 10 - countOfA - countOfB);
console.log(elements)
return;
}
elements.set(`${element.id}|${element.type}`, element.count);
})
I want to ask about another faster implementation if any. I estimated my big O will be O(n) (n is the total length of 3 arrays). If elements of arrays do not contain the same id.
Edit:
Big thanks to you all, but seems like there's one edge case. The answers couldn't handle
var arrayOfA = [
{
"type": "A", "count": 10, "id": "UID1"
},
{
"type": "A", "count": 20, "id": "UID2"
},
{
"type": "A", "count": 1, "id": "UID4"
},
];
const arrayOfB = [
{
"type": "B", "count": 5, "id": "UID1"
},
{
"type": "B", "count": 5, "id": "UID3"
},
{
"type": "B", "count": 1, "id": "UID3"
},
];
var arrayOfC = [
{
"type": "C", "count": 6, "id": "UID1"
},
{
"type": "C", "count": 6, "id": "UID4"
},
{
"type": "C", "count": 3, "id": "UID2"
},
{
"type": "C", "count": 3, "id": "UID3"
},
]
In arrayOfB, I have the UID3 occurs twice, so your answers doesn't seem to work on that case.
Instead of a Set for a maxed id, you could sum the count for every id and use it for all following arrays.
const
getKey = (...a) => a.join('|'),
rawData = [{ type: "A", count: 10, id: "UID1" }, { type: "A", count: 20, id: "UID2" }, { type: "A", count: 1, id: "UID4" }],
rawData3 = [{ type: "B", count: 5, id: "UID1" }, { type: "B", count: 5, id: "UID3" }],
rawData2 = [{ type: "C", count: 6, id: "UID1" }, { type: "C", count: 6, id: "UID4" }, { type: "C", count: 3, id: "UID2" }, { type: "C", count: 3, id: "UID3" }],
elements = new Map,
sums = new Map;
[rawData, rawData3, rawData2].forEach(a => a.forEach(({ type, count, id }) => {
var sum = sums.get(id) || 0,
key = getKey(id, type);
sums.set(id, sum + count);
if (sum >= 10) return;
if (sum + count > 10) {
if (10 - sum > 0) elements.set(key, 10 - sum);
return;
}
elements.set(key, count);
}));
[...elements].map(a => console.log(a.join(': ')));
.as-console-wrapper { max-height: 100% !important; top: 0; }
Based on the assumption that you have missed to include "B" in your expected results set, two nested loops can provide the manipulation and filtering you want.
function getIdSummary(arrays) {
const maxValue = 10;
//Array of objects which we later conver to a map
//The aim is ease of indexing during the iterations
var summary = []
//A heler to find if a maxed uid is found in the summary
function isMaxed(uid) {
return summary.some(item => {
return item.uid === uid && item.count >= maxValue;
})
}
//Iterate all the arrays
arrays.forEach(anInputArray => {
//Iterate each array
anInputArray.forEach(item => {
if (!isMaxed(item.id)) {
summary.push({uid: item.id, type: item.type, count: item.count > maxValue ? 10 : item.count})
}
})
})
return new Map(summary.map(obj => {
return [obj.uid + '|' + obj.type, obj.count]
}))
}
var arrayOfA = [
{
"type": "A", "count": 10, "id": "UID1"
},
{
"type": "A", "count": 20, "id": "UID2"
},
{
"type": "A", "count": 1, "id": "UID4"
},
];
const arrayOfB = [
{
"type": "B", "count": 5, "id": "UID1"
},
{
"type": "B", "count": 5, "id": "UID3"
},
];
var arrayOfC = [
{
"type": "C", "count": 6, "id": "UID1"
},
{
"type": "C", "count": 6, "id": "UID4"
},
{
"type": "C", "count": 3, "id": "UID2"
},
{
"type": "C", "count": 3, "id": "UID3"
},
]
var m = getIdSummary([arrayOfA, arrayOfB, arrayOfC]);
console.log(Array.from(m));

Create new array with another structure in Javascript

I want to create a new array based on an original array but with merged data.
Every name key need to have merged date+time (format: YYYY-MM-DD HH:MM) with merged scores. All unique datetimes need to be available as key for each name.
ARRAY ORIGINAL:
"data": [{
"name": "A",
"history": [{
"created": "2017-05-16 00:00:00",
"score": "1"
},
{
"created": "2017-05-16 00:01:10",
"score": "1"
},
{
"created": "2017-05-16 00:01:30",
"score": "1"
}
]
},
{
"name": "B",
"history": [{
"created": "2017-05-16 00:01:00",
"score": "1"
}]
}
]
ARRAY THAT I WANT:
{
[A]: {
"2017-05-16 00:00": 1,
"2017-05-16 00:01": 2
},
[B]: {
"2017-05-16 00:00": 0,
"2017-05-16 00:01": 1
}
}
I hope you guys can help me out. I can't even think of an efficiƫnt way to do this, unfortunately. I tried to solve this issue with 5 foreach statements with no luck :(
You could use two arrays for names and times as closure and generate for all names and times a property with zero value.
var data = { data: [{ name: "A", history: [{ created: "2017-05-16 00:00:00", score: "1" }, { created: "2017-05-16 00:01:10", score: "1" }, { created: "2017-05-16 00:01:30", score: "1" }] }, { name: "B", history: [{ created: "2017-05-16 00:01:00", score: "1" }] }] },
result = data.data.reduce(function (names, times) {
return function (r, a) {
if (!r[a.name]) {
r[a.name] = {};
times.forEach(function (time) {
r[a.name][time] = 0;
});
names.push(a.name);
}
a.history.forEach(function (o) {
var time = o.created.slice(0, 16);
if (times.indexOf(time) === -1) {
names.forEach(function (name) {
r[name][time] = 0;
});
times.push(time);
}
r[a.name][time] += +o.score;
});
return r;
};
}([], []), {});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You have to create an object not an array, As arrays cannot have a key-value pair in javascript. There is no associative array concept in javascript. You have to use objects in javascript for that.
Here is how you can do what you are trying to achieve using objects.
value = {
"data": [{
"name": "A",
"history": [{
"created": "2017-05-16 00:00:00",
"score": "1"
},
{
"created": "2017-05-16 00:01:10",
"score": "1"
},
{
"created": "2017-05-16 00:01:30",
"score": "1"
}
]},
{
"name": "B",
"history": [{
"created": "2017-05-16 00:01:00",
"score": "1"
}]
}]
};
var result ={};
value.data.forEach(function(v){
var score = {};
for(var i=0;i<v.history.length;i++){
score[v.history[i].created] = v.history[i].score;
}
result[v.name] = score;
});
console.log(result);
Now you can access data as result.A or result[A] and result.B or result[B]
SNIPPET
value = {
"data": [{
"name": "A",
"history": [{
"created": "2017-05-16 00:00:00",
"score": "1"
},
{
"created": "2017-05-16 00:01:10",
"score": "1"
},
{
"created": "2017-05-16 00:01:30",
"score": "1"
}
]
},
{
"name": "B",
"history": [{
"created": "2017-05-16 00:01:00",
"score": "1"
}]
}
]
};
var result = {};
value.data.forEach(function(v) {
var score = {};
for (var i = 0; i < v.history.length; i++) {
score[v.history[i].created] = v.history[i].score;
}
result[v.name] = score;
});
console.log(result);

Change representation of JSON object to explicit key/value format

I have the following JSON:
{
"temperature": "22.2",
"power": "6",
"current": "156"
}
and I need to convert it to this explicit structure:
{
"key": "temperature",
"value": "22.2"
},
{
"key": "power",
"value": "6"
},
{
"key": "current",
"value": "156"
}
Is there an elegant, simple and quick way to do this?
Best, thx
var newStructure = Object.keys(obj).map(function(key){
return {'key':key, 'value':obj[key]}
})
Example
var obj = {
"temperature": "22.2",
"power": "6",
"current": "156"
}
var arr = Object.keys(obj).map(function(key){return {'key':key,'value':obj[key]}})
console.log(arr)
Object.hashToKeyValuePairs = function (hash) {
var ret = [];
for (var i in hash)
ret.push({ key: i, value: hash[i]});
return ret;
};
// example
document.body.innerHTML = JSON.stringify(
Object.hashToKeyValuePairs({ a: 1, b: 2, c: 3 })
);

Categories