Merging Same JSON Element - javascript

How can you merge this JSON data. Simply merging the same objects and adding the different "product_code" into an array from the same JSON element dependent on the "product_web_name".
{
"search_result": {
"results": [
{
"product_id": "1",
"product_code": "Aa",
"product_description": "test desc a",
"product_web_name": "Product A"
},
{
"product_id": "2",
"product_code": "Bb111",
"product_description": "test desc b",
"product_web_name": "Product B",
},
{
"product_id": "2",
"product_code": "Bb222",
"product_description": "test desc b",
"product_web_name": "Product B"
},
{
"product_id": "2",
"product_code": "Bb333",
"product_description": "test desc b",
"product_web_name": "Product B",
}
]
}
}
The Final output results or the outcome would be something like this
{
"search_result": {
"results": [
{
"product_id": "1",
"product_code": "Aa",
"product_description": "test desc a",
"product_web_name": "Product A"
},
{
"product_id": "2",
"product_code": [
{
"product_code_id":"1",
"product_code": "Bb111"
},
{
"product_code_id":"2",
"product_code": "Bb222"
},
{
"product_code_id":"3",
"product_code": "Bb333"
}
],
"product_description": "test desc b",
"product_web_name": "Product B",
}
]
}
}
I want to merge the JSON data with adding the same element. I have tried the code so far.
var mergethis = {};
data = result.search_result.results.filter(function(entry) {
var previous;
if(mergethis.hasOwnProperty(entry.product_web_name)) {
previous = mergethis[entry.product_web_name];
previous.data.push(entry.data);
return false;
}
if (!Array.isArray(entry.data)) {
entry.data = [entry.data];
}
mergethis[entry.product_web_name] = entry;
return true;
});
console.log(mergethis);

Here's a snippet below to get you started, you can massage the output as needed. All of this came from using Array.prototype.reduce Array.prototype.map and Object.prototype.keys. A utility tool may also help simplify if you look at lodash or underscore
var data = {
"search_result": {
"results": [
{
"product_id": "1",
"product_code": "Aa",
"product_description": "test desc a",
"product_web_name": "Product A"
},
{
"product_id": "2",
"product_code": "Bb111",
"product_description": "test desc b",
"product_web_name": "Product B",
},
{
"product_id": "2",
"product_code": "Bb222",
"product_description": "test desc b",
"product_web_name": "Product B"
},
{
"product_id": "2",
"product_code": "Bb333",
"product_description": "test desc b",
"product_web_name": "Product B",
}
]
}
};
var grouped = data.search_result.results.reduce(function(acc, value) {
var groupArray = acc[value.product_id];
if (!groupArray) {
groupArray = [];
acc[value.product_id] = groupArray;
}
groupArray.push(value);
return acc;
}, {});
//console.log(grouped);
data.search_result.results = Object.keys(grouped).map(function(key) {
//return grouped[key][0];
return {
"product_id": grouped[key][0].product_id,
"product_description": grouped[key][0].product_description,
"product_code": grouped[key].length === 1 ? grouped[key][0].product_code : grouped[key]
};
});
console.log(data);

for(var i = 0 ; i < a.search_result.results.length; i++){
switch(a.search_result.results[i].product_web_name){
case 'Product A':
a.search_result.results[i].product_code = 'something1';
break;
case 'Product B':
a.search_result.results[i].product_code = 'something2';
break;
default :
a.search_result.results[i].product_code = 'something3';
}
}

Related

Grouping a multilevel array of objects

I am trying to learn javascript reduce and map an I came across some difficulties.
I have an array with the following format. The id of the parent is same as the location_id of the child. I need to group the array into a nested format.
arr = [
{
"id": 4583211,
"name": "Location 1",
"location_id": null,
},
{
"id": 7458894,
"name": "Location 12",
"location_id": 4583211
},
{
"id": 7463953,
"name": "Location 13",
"location_id": 4583211
},
{
"id": 80302210,
"name": "Location 121",
"location_id": 7458894
},
{
"id": 80302219,
"name": "Location 122",
"location_id": 7458894
},
{
"id": 7464314,
"name": "Location 131",
"location_id": 7463953
},
{
"id": 4583216,
"name": "Location 2",
"location_id": null,
},
{
"id": 3566353,
"name": "Location 21",
"location_id": 4583216
},
]
This array should be grouped as:
result = [
{
"id": 4583211,
"name": "Location 1",
"locations": [
{
"id": 7458894,
"name": "Location 12",
"locations": [
{
"id": 80302210,
"name": "Location 121"
},
{
"id": 80302219,
"name": "Location 122"
}
]
},
{
"id": 7463953,
"name": "Location 13",
"locations": [
{
"id": 7464314,
"name": "Location 131"
}
]
}
]
},
{
"id": 4583216,
"name": "Location 2",
"locations": [
{
"id": 3566353,
"name": "Location 21"
}
]
}
]
I tried to group it using the following method found on SO but it gives different result.
result = arr.reduce(function (r, a) {
r[a.location_id] = r[a.location_id] || [];
r[a.location_id].push(a);
return r;
}, Object.create(null));
You could do this using reduce and recursion you just need to check if parent is equal to current elements location_id.
const data = [{"id":4583211,"name":"Location 1","location_id":null},{"id":7458894,"name":"Location 12","location_id":4583211},{"id":7463953,"name":"Location 13","location_id":4583211},{"id":80302210,"name":"Location 121","location_id":7458894},{"id":80302219,"name":"Location 122","location_id":7458894},{"id":7464314,"name":"Location 131","location_id":7463953},{"id":4583216,"name":"Location 2","location_id":null},{"id":3566353,"name":"Location 21","location_id":4583216}]
function create(data, parent = null) {
return data.reduce((r, e) => {
if(parent == e.location_id) {
const o = { id: e.id, name: e.name }
const children = create(data, e.id);
if(children.length) o.locations = children;
r.push(o)
}
return r
}, [])
}
console.log(create(data))

Array of objects to objects with properties as keys

I need some help to get objects from an array of object with keys coming from nested properties of the objects in the initial array. This is the initial array :
[
{
"id":{
"colName":"columnA",
"recId":"123"
},
"desc":"this is a description for A",
"resCode":"-1"
},
{
"id":{
"colName":"columnB",
"recId":"123"
},
"desc":"this is a description for B",
"resCode":"-1"
},
{
"id":{
"colName":"columnC",
"recId":"234"
},
"desc":"description for column c ",
"resCode":"-1"
}
];
And my desired output would be this:
{
123: {
columnA: {
desc: "this is a description for A",
rescode: "-1"
}
columnB: {
desc: "this is a description for B",
rescode: "-1"
}
},
234: {
columnC: {
desc: "description for column c ",
resCode: "-1",
}
}
}
I tried to use reduce to do so but I have an issue. I don't know how (and when) to "clear" the temp variable so I can only have column names belonging to one recId.
const initialArray = [
{
"id": {
"colName": "columnA",
"recId": "123"
},
"desc": "this is a description for A",
"resCode": "-1"
},
{
"id": {
"colName": "columnB",
"recId": "123"
},
"desc": "this is a description for B",
"resCode": "-1"
},
{
"id": {
"colName": "columnC",
"recId": "234"
},
"desc": "description for column c ",
"resCode": "-1"
}
];
let temp = {};
const mappedObj = initialArray.reduce((obj, item) => {
temp[item.id.colName] = Object.assign({}, {desc: item.desc}, {resCode: item.resCode} );
obj[item.id['recId']] = Object.assign({}, temp);
return obj;
}, {});
console.log(mappedObj);
You don't need to maintain a temp variable outside of reduce, you can simply process the same actions in reduce itself
const initialArray = [
{
"id": {
"colName": "columnA",
"recId": "123"
},
"desc": "this is a description for A",
"resCode": "-1"
},
{
"id": {
"colName": "columnB",
"recId": "123"
},
"desc": "this is a description for B",
"resCode": "-1"
},
{
"id": {
"colName": "columnC",
"recId": "234"
},
"desc": "description for column c ",
"resCode": "-1"
}
];
const mappedObj = initialArray.reduce((obj, item) => {
obj[item.id.recId] = {...(obj[item.id.recId] || {}), [item.id.colName]: {desc: item.desc, resCode: item.resCode}}
return obj;
}, {});
console.log(mappedObj);

Count length of items in nested js object

Given an array like this, how would I get a count of all charts in a particular category. Each category can have multiple or no groups.
{
"categories":[
{
"title":"category 1",
"id":"cat1",
"groups":[
{
"title":"group 1",
"id":"grp1",
"charts":[
{
"title":"chart 1",
"id":"chart1",
"type":"line"
}
]
}
]
},
{
"title":"category 2",
"id":"cat2",
"charts":[
{
"title":"chart 2",
"id":"chart2",
"type":"line"
}
]
},
{
"title":"category 3",
"id":"cat3",
"charts":[
{
"title":"chart 3",
"id":"chart3",
"type":"line"
}
]
}
]
}
Is a one-liner okay?
Assuming data is your JSON structure:
data.categories
.map(c => [
c.title,
c.groups ?
c.groups.map(g => g.charts.length).reduce((a, b) => a+b) :
c.charts.length
])
var object = {
"categories": [{
"title": "category 1",
"id": "cat1",
"groups": [{
"title": "group 1",
"id": "grp1",
"charts": [{
"title": "chart 1",
"id": "chart1",
"type": "line"
}]
}]
}, {
"title": "category 2",
"id": "cat2",
"charts": [{
"title": "chart 2",
"id": "chart2",
"type": "line"
}]
}, {
"title": "category 3",
"id": "cat3",
"charts": [{
"title": "chart 3",
"id": "chart3",
"type": "line"
}]
}]
}
var groupPerCategories = [];
object.categories.forEach(function(category) {
var tot = 0;
if (category.groups != undefined) {
category.groups.forEach(function(group) {
if(group.charts != undefined){
tot += group.charts.length;
}
});
}
if (category.charts != undefined) {
tot += category.charts.length;
}
console.log(tot);
});
You could count the properties with default.
var data = { "categories": [{ "title": "category 1", "id": "cat1", "groups": [{ "title": "group 1", "id": "grp1", "charts": [{ "title": "chart 1", "id": "chart1", "type": "line" }] }] }, { "title": "category 2", "id": "cat2", "charts": [{ "title": "chart 2", "id": "chart2", "type": "line" }] }, { "title": "category 3", "id": "cat3", "charts": [{ "title": "chart 3", "id": "chart3", "type": "line" }] }] },
count = {};
data.categories.forEach(function (a) {
var countCharts = function (r, a) {
return r + (a.charts || []).length;
};
count[a.title] = (count[a.title] || 0) +
(a.groups ||[]).reduce(countCharts, 0) +
countCharts(0, a);
});
console.log(count);
Hope this will help you :)
var categories = [
{
"title":"category 1",
"id":"cat1",
"groups":[
{
"title":"group 1",
"id":"grp1",
"charts":[
{
"title":"chart 1",
"id":"chart1",
"type":"line"
}
]
}
]
},
{
"title":"category 2",
"id":"cat2",
"charts":[
{
"title":"chart 2",
"id":"chart2",
"type":"line"
}
]
},
{
"title":"category 3",
"id":"cat3",
"charts":[
{
"title":"chart 3",
"id":"chart3",
"type":"line"
},
{
"title":"chart 3",
"id":"chart3",
"type":"line"
},
{
"title":"chart 3",
"id":"chart3",
"type":"line"
}
]
},
{
"title":"category 4",
"id":"cat4",
"groups":[
{
"title":"group 4",
"id":"grp4",
"charts":[
{
"title":"chart 1",
"id":"chart1",
"type":"line"
},
{
"title":"chart 1",
"id":"chart1",
"type":"line"
}
]
}
]
}
];
function countCategoryItems(data, category) {
if(!data ) return 0
if(!category) return 0
var cat = _.filter(data, function(obj){ return obj.title == category; });
if(!cat.length) return 0
var groups = cat[0].groups || []
if(!groups.length) return cat[0].charts.length
var count = 0
for (var i=0;i<groups.length;i++) {
count += groups[i].charts.length
}
return count
}
$(function() {
console.log(countCategoryItems(categories, 'category 1'))
console.log(countCategoryItems(categories, 'category 2'))
console.log(countCategoryItems(categories, 'category 3'))
console.log(countCategoryItems(categories, 'category 4'))
})
<script src="http://underscorejs.org/underscore.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Javascript Loop and filter out the data thats null or empty

I have some data and I need to filter out the data thats null or empty and create a new data list thats filtered.
In this case sometimes "names" array is null so I need that data out.
{
"people": [
{
"id": "2",
"description": "desc here",
"names": [
{
"name": "name here",
},
{
"name": "name here",
}
],
"other": "0"
},
{
"id": "200",
"description": "desc here",
"names": null
"other": "0"
},
{
"id": "64",
"description": "desc here",
"names": [
{
"name": "name here",
},
{
"name": "name here",
}
],
"other": "1"
}
]
}
How can I do this?
You could iterate the arrays and objects recursive until a primitive is found. Then check and return the value.
function copy(object) {
var o;
if (Array.isArray(object)) {
return object.reduce(function (r, a) {
var v = copy(a);
v.names !== null && v.names !== '' && r.push(v);
return r;
}, []);
}
if (object !== null && typeof object === 'object') {
o = {};
Object.keys(object).forEach(function (k) {
o[k] = copy(object[k]);
});
return o;
}
return object;
}
var data = { people: [{ id: "2", description: "desc here", names: [{ id: "345", name: "name here", }, { id: "54", name: "name here", foo: "", }], other: "0" }, { id: "2", description: "desc here", names: null, other: "0" }, { id: "64", description: "desc here", names: [{ id: "87", name: "name here", }, { id: "53", name: "name here", }], other: "1" }] },
result = copy(data);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
var newArray = oldArray.filter(function(v){return v!==''});
new_array=yourObject.people.filter(function(elem){
return elem.names!==null && elem.names!==""
});

Jquery : transform nested json object to another json object

In javascript/jquery how do i achieve following
old_dataset = [
{
"dob": "xyz",
"name": {
"first": " abc",
"last": "lastname"
},
"start_date": {
"moth": "2",
"day": "5",
"year": 1
},
"children": [
{
"child": {
"id": "1",
"desc": "first child"
}
},
{
"child": {
"id": "2",
"desc": "second child"
}
}
]
},
{
"dob": "er",
"name": {
"first": " abc",
"last": "txt"
},
"start_date": {
"moth": "2",
"day": "5",
"year": 1
},
"children": [
{
"child": {
"id": "1",
"desc": "first child"
}
},
{
"child": {
"id": "2",
"desc": "second child"
}
}
]
}
]
Using jquery iterate over the above and change to following
new_dataset = [
{
"dob":"xyz",
"name": <first and last name values>
"start_date":<value of month day year>,
"children": [ {
child_id :1,
child_id : 2
},
]
},{
"dob":"er",
"name": <first and last name values>
"start_date":<value of month day year>,
"children": [ {
child_id :1,
child_id : 2
},
]
}]
If someone can give the code to transform the data it would help me to understand the iteration
You could do something like:
function transformDataset(oldDataset) {
var newDataset = [];
var newObj;
for (var i = 0; i < oldDataset.length; i++) {
newObj = transformObj(oldDataset[i]);
newDataset.push(newObj);
}
return newDataset;
}
function transformObj(obj) {
var children = obj.children;
obj.name = obj.name.first + ' ' + obj.name.last;
obj.start_date = obj.start_date.month + ' ' + obj.start_date.day + ' ' + obj.start_date.year;
obj.children = [];
for (var i = 0; i < children.length; i++) {
obj.children.push(children[i].child.id);
}
return obj;
}
var new_dataset = transformDataset(old_dataset);
Note that new_dataset will have an array of child id instead of an object with multiple child_id properties.
You also had a typo in old_dataset.start_date.month (was written moth)(or maybe that was intentional).
use map first to iterate the array data (old_dataset), replace element name & start_date with new value then return the array
const old_dataset = [
{
"dob": "xyz",
"name": {
"first": " abc",
"last": "lastname"
},
"start_date": {
"moth": "2",
"day": "5",
"year": 1
},
"children": [
{
"child": {
"id": "1",
"desc": "first child"
}
},
{
"child": {
"id": "2",
"desc": "second child"
}
}
]
},
{
"dob": "er",
"name": {
"first": " abc",
"last": "txt"
},
"start_date": {
"moth": "2",
"day": "5",
"year": 1
},
"children": [
{
"child": {
"id": "1",
"desc": "first child"
}
},
{
"child": {
"id": "2",
"desc": "second child"
}
}
]
}
]
let new_dataset = old_dataset.map((arr) => {
arr.name = `${arr.name.first} ${arr.name.last}`
arr.start_date = `${arr.start_date.moth} ${arr.start_date.day} ${arr.start_date.year}`
return arr
})
console.log(new_dataset)

Categories

Resources