Parse json to especific format [closed] - javascript

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
How i can parse this json
[
{"CODE":"1","MONTH":"1","TOTAL":78},
{"CODE":"1","MONTH":"2","TOTAL":122},
{"CODE":"1","MONTH":"3","TOTAL":102},
{"CODE":"1","MONTH":"4","TOTAL":65},
{"CODE":"1","MONTH":"5","TOTAL":134},
{"CODE":"1","MONTH":"6","TOTAL":88},
{"CODE":"1","MONTH":"7","TOTAL":77},
{"CODE":"1","MONTH":"8","TOTAL":58},
{"CODE":"1","MONTH":"9","TOTAL":67},
{"CODE":"1","MONTH":"10","TOTAL":69},
{"CODE":"2","MONTH":"5","TOTAL":4},
{"CODE":"2","MONTH":"6","TOTAL":87},
{"CODE":"2","MONTH":"7","TOTAL":81},
{"CODE":"2","MONTH":"8","TOTAL":105},
{"CODE":"2","MONTH":"9","TOTAL":112},
{"CODE":"2","MONTH":"10","TOTAL":85},
]
To this format
series: [{
name: '1',
data: [78, 122, 102, 65, 134, 88, 77, 58, 67, 69, 0, 0]
}, {
name: '2',
data: [0, 0, 0, 0, 4, 87, 81, 105, 112, 85, 0, 0]
}]
With an javascript or jquery function efficiently?
In the Json every row represents a total value for each code (1 or 2) per month
For the CODE=1 i have totals only for ten months (month 1 = jan, month 2= feb ... month 10= oct)
For the CODE=2 i have totals only for five months between may and octuber.
In this array [78, 122, 102, 65, 134, 88, 77, 58, 67, 69, 0, 0]
78 is the total for january, 122 for february, 102 for march ...
For those months that i do not have a total, like november or december for example , i need to put a 0
My json will return more info, with more codes i can't use brute force
Thanks in advance
JC

You can run a loop like the following:
var temp = [];
for (var i =0; i< data.length;i++) {
var obj = data[i],
dup = false;
for (var j = 0; j < temp.length; j++) {
var item = temp[j];
if (obj.CODE == item.name) {
item.data.push(obj.TOTAL);
dup = true;
break;
}
}
if (!dup) {
temp.push({
name: obj.CODE,
data: [obj.TOTAL]
});
}
}
var data = [{
"CODE": "1",
"MONTH": "1",
"TOTAL": 78
}, {
"CODE": "1",
"MONTH": "2",
"TOTAL": 122
}, {
"CODE": "1",
"MONTH": "3",
"TOTAL": 102
}, {
"CODE": "1",
"MONTH": "4",
"TOTAL": 65
}, {
"CODE": "1",
"MONTH": "5",
"TOTAL": 134
}, {
"CODE": "1",
"MONTH": "6",
"TOTAL": 88
}, {
"CODE": "1",
"MONTH": "7",
"TOTAL": 77
}, {
"CODE": "1",
"MONTH": "8",
"TOTAL": 58
}, {
"CODE": "1",
"MONTH": "9",
"TOTAL": 67
}, {
"CODE": "1",
"MONTH": "10",
"TOTAL": 69
},
{
"CODE": "2",
"MONTH": "5",
"TOTAL": 4
}, {
"CODE": "2",
"MONTH": "6",
"TOTAL": 87
}, {
"CODE": "2",
"MONTH": "7",
"TOTAL": 81
}, {
"CODE": "2",
"MONTH": "8",
"TOTAL": 105
}, {
"CODE": "2",
"MONTH": "9",
"TOTAL": 112
}, {
"CODE": "2",
"MONTH": "10",
"TOTAL": 85
}
];
var temp = [];
for (var i = 0; i < data.length; i++) {
var obj = data[i],
dup = false;
for (var j = 0; j < temp.length; j++) {
var item = temp[j];
if (obj.CODE == item.name) {
item.data.push(obj.TOTAL);
dup = true;
break;
}
}
if (!dup) {
temp.push({
name: obj.CODE,
data: [obj.TOTAL]
});
}
}
console.log(temp);
<p>Check browser console <sup>F12</sup> to see the result<p>

Here is a brute force example which does only what was requested.
working jsfiddle
var originalData = [
{"CODE":"1","MONTH":"1","TOTAL":78},
{"CODE":"1","MONTH":"2","TOTAL":122},
{"CODE":"1","MONTH":"3","TOTAL":102},
{"CODE":"1","MONTH":"4","TOTAL":65},
{"CODE":"1","MONTH":"5","TOTAL":134},
{"CODE":"1","MONTH":"6","TOTAL":88},
{"CODE":"1","MONTH":"7","TOTAL":77},
{"CODE":"1","MONTH":"8","TOTAL":58},
{"CODE":"1","MONTH":"9","TOTAL":67},
{"CODE":"1","MONTH":"10","TOTAL":69},
{"CODE":"2","MONTH":"5","TOTAL":4},
{"CODE":"2","MONTH":"6","TOTAL":87},
{"CODE":"2","MONTH":"7","TOTAL":81},
{"CODE":"2","MONTH":"8","TOTAL":105},
{"CODE":"2","MONTH":"9","TOTAL":112},
{"CODE":"2","MONTH":"10","TOTAL":85},
];
var newData={};
var tempData1=[];
var tempData2=[];
for (var ii=0;ii<originalData.length;ii++){
if (originalData[ii].CODE==="1"){
tempData1.push(originalData[ii].TOTAL);
}
else{
tempData2.push(originalData[ii].TOTAL);
}
}
newData['series'] =[ {name: '1',
data: tempData1},
{
name: '2',
data: tempData2
}];
console.log(JSON.stringify(newData));

var oData = [
{"CODE":"1","MONTH":"1","TOTAL":78},
{"CODE":"1","MONTH":"2","TOTAL":122},
{"CODE":"1","MONTH":"3","TOTAL":102},
{"CODE":"1","MONTH":"4","TOTAL":65},
{"CODE":"1","MONTH":"5","TOTAL":134},
{"CODE":"1","MONTH":"6","TOTAL":88},
{"CODE":"1","MONTH":"7","TOTAL":77},
{"CODE":"1","MONTH":"8","TOTAL":58},
{"CODE":"1","MONTH":"9","TOTAL":67},
{"CODE":"1","MONTH":"10","TOTAL":69},
{"CODE":"2","MONTH":"5","TOTAL":4},
{"CODE":"2","MONTH":"6","TOTAL":87},
{"CODE":"2","MONTH":"7","TOTAL":81},
{"CODE":"2","MONTH":"8","TOTAL":105},
{"CODE":"2","MONTH":"9","TOTAL":112},
{"CODE":"2","MONTH":"10","TOTAL":85},
],
nData = [{ name: '1', data: [] }, { name: '2', data: [] }];
for (var n = 1; n <= 12; n++) {
var d1 = oData.filter(function(d) {
return d.CODE == '1' && d.MONTH == n;
}),
d2 = oData.filter(function(d) {
return d.CODE == '2' && d.MONTH == n;
});
nData[0].data.push(d1.length ? d1[0].TOTAL : 0);
nData[1].data.push(d2.length ? d2[0].TOTAL : 0);
}
$('pre.out').text( JSON.stringify(nData) );
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<pre class="out"></pre>

Related

Merge arrays matching a particular key value in JavaScript

I have an array which is like this:
var arr = [{
"date": "JAN",
"value": 5,
"weight": 3
}, {
"date": "JAN",
"value": 4,
"weight": 23
}, {
"date": "FEB",
"value": 9,
"weight": 1
}, {
"date": "FEB",
"value": 10,
"weight": 30
}]
I want to match the primary key which is heredate. Matching this I want to merge the rest of the key values and get this following output:
[{
"date": "JAN",
"value": [5, 4],
"weight": [3, 23]
}, {
"date": "FEB",
"value": [9, 10],
"weight": [1, 30]
}]
I have written a function like this but can't figure out how to concat the key values:
var arr = [{
"date": "JAN",
"value": 5,
"weight": 3
}, {
"date": "JAN",
"value": 4,
"weight": 23
}, {
"date": "FEB",
"value": 9,
"weight": 1
}, {
"date": "FEB",
"value": 10,
"weight": 30
}]
const transform = (arr, primaryKey) => {
var newValue = [];
for (let i = 0; i < arr.length; i++) {
for (let j = 1; j < arr.length; j++) {
if (primaryKey[i] === primaryKey[j]) {
newValue.push({
...arr[i],
...arr[j]
});
}
}
}
return newValue
};
console.log(transform(arr,'date'))
Using Array#reduce, iterate over the list while updating a Map where the key is the primary-key and the value is the grouped object. In every iteration, create/update the pair.
Using Map#values, return the list of grouped objects
const transform = (arr, primaryKey) => [...
arr.reduce((map, { [primaryKey]: key, ...e }) => {
const { [primaryKey]: k, ...props } = map.get(key) ?? {};
for(let prop in e) {
props[prop] = [...(props[prop] ?? []), e[prop]];
}
map.set(key, { [primaryKey]: key, ...props });
return map;
}, new Map)
.values()
];
const arr = [ { "date": "JAN", "value": 5, "weight": 3 }, { "date": "JAN", "value": 4, "weight": 23 }, { "date": "FEB", "value": 9, "weight": 1 }, { "date": "FEB", "value": 10, "weight": 30 } ];
console.log( transform(arr, 'date') );
The following code should work:
const transform = (arr, primaryKey) => {
var newValue = [];
for(let i = 0; i < arr.length; i++){
arr[i]["value"] = [arr[i]["value"]];
arr[i]["weight"] = [arr[i]["weight"]];
}
newValue.push(arr[0])
for(let i = 1; i < arr.length; i++){
let contains = false;
for(let j = 0; j < newValue.length; j++){
if(newValue[j][primaryKey] == arr[i][primaryKey]){
newValue[j]["value"].push(arr[i]["value"][0]);
newValue[j]["weight"].push(arr[i]["weight"][0]);
contains = true;
}
}
if(!contains){
newValue.push(arr[i]);
}
}
return newValue
};
var arr = [{
"date": "JAN",
"value": 5,
"weight": 3
}, {
"date": "JAN",
"value": 4,
"weight": 23
}, {
"date": "FEB",
"value": 9,
"weight": 1
}, {
"date": "FEB",
"value": 10,
"weight": 30
}]
var newthing = transform(arr,"date");
console.log(newthing);
Output:
[ { date: 'JAN', value: [ 5, 4 ], weight: [ 3, 23 ] },
{ date: 'FEB', value: [ 9, 10 ], weight: [ 1, 30 ] } ]
The way this code works is that first, we turn the values of the keys for "value" and "weight" into lists.
Then, we begin by pushing the first element of arr into newValue.
From here, we do a nested for loop to iterate through the remaining of arr and newValue:
If the value of "date" for every element of arr already exists in newValue, then we will push in the values of "value" and "weight" that belongs to arr.
However, if it does not exist, then we will simply push that element inside of newValue.
I hope this helped answer your question! Pleas let me know if you need any further help or clarification :)
Combining a couple of reduce can also do the same job:
const arr = [{
"date": "JAN",
"value": 5,
"weight": 3
}, {
"date": "JAN",
"value": 4,
"weight": 23
}, {
"date": "FEB",
"value": 9,
"weight": 1
}, {
"date": "FEB",
"value": 10,
"weight": 30
}]
const arrayMappedByDate = arr.reduce((acc, curData) => {
if (acc[curData.date]) {
acc[curData.date].push(curData)
} else {
acc[curData.date] = [curData]
}
return acc
}, {})
const transformedArray = Object.entries(arrayMappedByDate).map(([dateInit, data]) => {
const normalized = data.reduce((acc, cur) => {
if (acc.date) {
acc.value.push(cur.value)
acc.weight.push(cur.weight)
} else {
acc = {
date: cur.date,
value: [cur.value],
weight: [cur.weight]
}
}
return acc
}, {})
return { [dateInit]: normalized }
})
console.log(transformedArray)

Create dynamic object with dynamic keys and non dynamic

I am trying to create nested objects with some dynamic and not dynamic fields
this is my dataset let method = {
"97": {
"mini_id": 75,
"score": "2",
"fe_id": 97
},
"98": {
"mini_id": 75,
"score": "2",
"fe_id": 98
},
"169": {
"mini_id": 76,
"score": "1",
"fe_id": 169
},
"170": {
"mini_id": 76,
"score": "1",
"fe_id": 170
},
"171": {
"mini_id": 76,
"score": "1",
"fe_id": 171
},
"172": {
"mini_id": 76,
"score": "3",
"fe_id": 172
}
}
And I am trying to have the data in the format of
var reduced = Object.values(arr).reduce((c,v) => {
c[v.mini_id] = c[v.mini_id] || {};
c[v.mini_id]["fees"][v.fe_id] = c[v.mini_id]["fees"][v.fe_id] || {};
return c;
}, {})
I want my dictionary to look like :
{75: {fees: {97: {....}}}}
Looks like it doesn't like dynamic keys to be mixed with non dynamic. Any suggestions?
The following code snippet might help you,
const arr = {
97: {
mini_id: 75,
score: "2",
fe_id: 97,
},
98: {
mini_id: 75,
score: "2",
fe_id: 98,
},
169: {
mini_id: 76,
score: "1",
fe_id: 169,
},
170: {
mini_id: 76,
score: "1",
fe_id: 170,
},
171: {
mini_id: 76,
score: "1",
fe_id: 171,
},
172: {
mini_id: 76,
score: "3",
fe_id: 172,
},
};
const reduced = Object.values(arr).reduce((c, v) => {
c[v.mini_id] = c[v.mini_id] ?? { fees: {} };
c[v.mini_id].fees[v.fe_id] = c[v.mini_id].fees[v.fe_id] ?? {};
return c;
}, {})
console.log(reduced);

JavaScript sort a dictionary array

I have a question about sorting a dictionary object is JS es6. I am trying to filter the array but still keep the structure of an array in each month's object. Here is a mock of the data:
"soldListings": {
"Jan - 2020": [
{
"id": 159,
"user_id": 1,
"type_id": 1,
},
{
"id": 173,
"user_id": 1,
"type_id": 1,
},
{
"id": 563,
"user_id": 1,
"type_id": 2,
}
],
"Dec - 2019": [
{
"id": 183,
"user_id": 1,
"type_id": 1,
}
],
"Oct - 2019": [
{
"id": 176,
"user_id": 1,
"type_id": 1,
}
]
}
If it were a flat array of objects i would do something like:
typeFilter = data.filter((listing) => {
if(listing.type_id){
return listing.type_id == this.state.soldListTypeFilter ;
}
});
UPDATE
I need the output to be in the same format as the input. For example if i were to filter the object by type_id = 2 it would return this:
"soldListings": {
"Jan - 2020": [
{
"id": 563,
"user_id": 1,
"type_id": 2,
}
],
"Dec - 2019": [
],
"Oct - 2019": [
]
}
Use keySort function for this problem, for un-integer keys
Read https://stackoverflow.com/a/23202095/7146552
keySort( object, sortfn? )
function keySort(obj, sort) {
var keys = Object.keys(obj);
keys = keys.sort(sort);
var sortedObject = {};
for (var i = 0; i < keys.length; i++) {
sortedObject[keys[i]] = obj[keys[i]]
}
return sortedObject;
}
// Using
var obj = {
"z:": "Zvalue",
"a": "AValue"
};
console.log(obj);
obj = keySort(obj);
// or
obj = keySort(obj, (a, b) => {
return a > b ? 1 : -1
});
console.log(obj)
On your Question Test
function keySort(obj, sort) {
var keys = Object.keys(obj);
keys = keys.sort(sort);
var sortedObject = {};
for (var i = 0; i < keys.length; i++) {
sortedObject[keys[i]] = obj[keys[i]]
}
return sortedObject;
}
data = {
"Jan - 2020": [{
"id": 159,
"user_id": 1,
"type_id": 1,
},
{
"id": 173,
"user_id": 1,
"type_id": 1,
},
{
"id": 563,
"user_id": 1,
"type_id": 2,
}
],
"Dec - 2019": [{
"id": 183,
"user_id": 1,
"type_id": 1,
}],
"Oct - 2019": [{
"id": 176,
"user_id": 1,
"type_id": 1,
}]
}
data = keySort(data,function(a,b){
adate = new Date(a);
bdate = new Date(b);
return adate>bdate ? 1 : -1;
})
console.log(data);

How to groupBy an attribute inside the second array with javascript

I am trying to convert an array object to a new set of arrays grouped by their value. In this case, it is the date value.
What I have tried in in the below code, but I didn't get the results of what I wanted. Can you please help me find the right solution for this problem?
INPUT
let array = [
{
"category": {
"code": "1558950145861"},
"lines": [
{
"date": "2020-02-26",
"price": 9260,
"dispo": 5
},
{
"date": "2020-02-29",
"price": 6300,
"dispo": 9
},
{
"date": "2020-04-01",
"price": 7700,
"dispo": 23
}
]
},
{
"category": {
"code": "1788858954441"
},
"lines": [
{
"date": "2020-02-26",
"price": 6260,
"dispo": 2
},
{
"date": "2020-02-29",
"price": 5500,
"dispo": 4
},
{
"date": "2020-04-01",
"price": 840,
"dispo": 7
}
]
}
];
Desired OUTPUT
[{
"date": "2020-02-26",
"lines": [{
"price": 9260,
"dispo": 5
}, {
"price": 6260,
"dispo": 2
}]
}, {
"date": "2020-02-29",
"lines": [{
"price": 6300,
"dispo": 9
}, {
"price": 5500,
"dispo": 4
}]
}, {
"date": "2020-04-01",
"lines": [{
"price": 7700,
"dispo": 23
}, {
"price": 840,
"dispo": 7
}]
}]
code that I wrote
var result = (_array)
.groupBy(x => {
for (let j = 0; j < x.lines.length; j += 1) {
return x.lines[j].date;
}
})
.map((value, key) => ({
date: key,
lines: value
})).value();
I want my code to generate the desired output, but it isn't doing that. What might I be doing wrong?
try this
let array = [{ "category": { "code": "1558950145861" }, "lines": [{ "date": "2020-02-26", "price": 9260, "dispo": 5 }, { "date": "2020-02-29", "price": 6300, "dispo": 9 }, { "date": "2020-04-01", "price": 7700, "dispo": 23 }] }, { "category": { "code": "1788858954441" }, "lines": [{ "date": "2020-02-26", "price": 6260, "dispo": 2 }, { "date": "2020-02-29", "price": 5500, "dispo": 4 }, { "date": "2020-04-01", "price": 840, "dispo": 7 }] }]
const groupBy = (arr) => arr.reduce((acc, ele)=>( (acc[ele.date] = acc[ele.date] || []).push(ele), acc),{})
const all = [].concat(...array.map(ele=> ele.lines))
const format = ele => ele.map(({price, dispo})=>({price, dispo}))
console.log(Object.entries(groupBy(all)).map(([date, lines])=> ({date, lines: format(lines)})))
Try something like this :
var out = {}
for (let i = 0; i < array.length; i++) {
for (let j = 0; j < array[i]["lines"].length; j++) {
let e = array[i]["lines"][j];
if (!out[e["date"]]) {
out[e["date"]] = [];
}
out[e["date"]].push({"price": e["price"], "dispo": e["dispo"]});
}
}
var result = [];
for (let k in out) {
result.push({"date": k, "lines": out[k]});
}
The result variable has the desired output format.
You don't appear to need the category value, so first I'd merge the lines into a single array where you can groupBy from there:
// using your input called 'array'
// First collect just the line arrays:
var arrayOfLineArrays=array.map(category => category.lines);
// Merge them into one bigger array:
var allLines = _.flatten(arrayOfLineArrays);
// Now you can groupBy with ease:
var dateGroupsObject = _(allLines).groupBy(line => line.date);
// And map to an array:
var result = _.values(_.mapObject(dateGroupsObject, (value, key) => ({
date: key,
lines: value
}))));

Trying to merge two arrays

Below is my json stored in :
$scope.regions = [];
{
"id": 100,
"regions": [
{
"id": 10,
"name": "Abc",
"rank": 0,
},
{
"id": 20,
"name": "Pqr",
"rank": 1,
},
{
"id": 30,
"name": "Lmn",
"rank": 2,
},
{
"id": 40,
"name": "xyz",
"rank": 3,
},
{
"id": 50,
"name": "GGG",
"rank": 4,
},
{
"id": 60,
"name": "YYY",
"rank": 5,
}
]
}
This is my another json stored in :
$scope.regionList = [];
var highestOrder = 3;
"regions": [
{
"id": 40,
"name": "xyz",
"rank": 0,
},
{
"id": 50,
"name": "GGG",
"rank": 1,
},
{
"id": 60,
"name": "YYY",
"rank": 2,
}
Now I want to merge $scope.regionList in to $scope.regions but for those records which are matching in both $scope.regionList and $scope.regions I would like to replace records of $scope.regions with $scope.regionList (only common records from both list).
And first non matching records from $scope.regionList will have order start using highestOrder and will keep incrementing for each non-matching records so final output will be like below :
Expected output :
"regions": [
{
"id": 10,
"name": "Abc",
"rank": 3,
},
{
"id": 20,
"name": "Pqr",
"rank": 4,
},
{
"id": 30,
"name": "Lmn",
"rank": 5,
},
{
"id": 40,
"name": "xyz",
"rank": 0,
},
{
"id": 50,
"name": "GGG",
"rank": 1,
},
{
"id": 60,
"name": "YYY",
"rank": 2,
}
As Abc is is the first non matching record so it will have order 3 and rest other will have order no from 3 i.e 4,5 6, etc.
My code:
var highestOrder = 3;
var found = false;
for (var i = 0; i < $scope.regions.length; i++) {
if ($scope.regions[i].id == 100) {
found = true;
for (var j = 0; j < $scope.regionList.length; j++) {
for (var k = 0; k < $scope.regions[i].regions.length; k++) {
if ($scope.regions[i].regions[k].id == $scope.regionList[j].id) {
$scope.regions[i].regions[k].rank = $scope.regionList[j].rank;
}
else {
$scope.regions[i].regions[k].rank = highestOrder;
highestOrder = highestOrder + 1;
}
}
}
}
if (found)
break;
}
var regions = {
"id": 100,
"regions": [{
"id": 10,
"name": "Abc",
"rank": 0,
},
{
"id": 20,
"name": "Pqr",
"rank": 1,
},
{
"id": 30,
"name": "Lmn",
"rank": 2,
},
{
"id": 40,
"name": "xyz",
"rank": 3,
},
{
"id": 50,
"name": "GGG",
"rank": 4,
},
{
"id": 60,
"name": "YYY",
"rank": 5,
}
]
}
var highestOrder = 3;
var found = false;
var regionList = [{
"id": 40,
"name": "xyz",
"rank": 0,
},
{
"id": 50,
"name": "GGG",
"rank": 1,
},
{
"id": 60,
"name": "YYY",
"rank": 2
}
]
for (var i = 0; i < regions.length; i++) {
if (regions[i].id == 100) {
found = true;
for (var j = 0; j < regionList.length; j++) {
for (var k = 0; k < regions[i].regions.length; k++) {
if (regions[i].regions[k].id == regionList[j].id) {
regions[i].regions[k].rank = regionList[j].rank;
} else {
regions[i].regions[k].rank = highestOrder;
highestOrder = highestOrder + 1;
}
}
}
}
if (found)
break;
}
console.log(regions)
You could use a hash table and build it with the elements of the array for updating.
Then iterate regions and update rank with either the hash's rank or with highestOrder. Increment highestOrder after assigning.
var $scope = { regions: [{ id: 100, regions: [{ id: 10, name: "Abc", rank: 0, }, { id: 20, name: "Pqr", rank: 1, }, { id: 30, name: "Lmn", rank: 2, }, { id: 40, name: "xyz", rank: 3, }, { id: 50, name: "GGG", rank: 4, }, { id: 60, name: "YYY", rank: 5, }] }] },
regionsUpdate = [{ id: 40, name: "xyz", rank: 0, }, { id: 50, name: "GGG", rank: 1, }, { id: 60, name: "YYY", rank: 2, }],
regionsId = 100,
highestOrder = 3,
hash = Object.create(null);
regionsUpdate.forEach(function (a) {
hash[a.id] = a;
});
$scope.regions.some(function (a) {
if (a.id === regionsId) {
a.regions.forEach(function (b) {
b.rank = hash[b.id] ? hash[b.id].rank : highestOrder++;
});
return true;
}
});
console.log($scope);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Categories

Resources