Underscore Create array of objects from JSON object - javascript

I have following JSON structure:
{
"shops": {
"categories": {
"cat_1": {
"id": "1",
"label": "Men's Fashions",
"Brands": [{
"id": "2",
"name": "Smith"
}]
},
"cat_2": {
"id": "2",
"label": "Restaurants",
"Brands": [{
"id": "3",
"name": "KFC"
}, {
"id": "4",
"name": "SUBWAY"
}, {
"id": "5",
"name": "MLD"
}, {
"id": "6",
"name": "THAI"
}]
},
"cat_3": {
"id": "3",
"label": "Specialty Shops",
"Brands": [{
"id": "7",
"name": "BODY SHOP"
}]
}
}
}
}
I'd like to achieve something like this:
[{
"categoryid": "1",
"id": "2",
"label": "Men's Fashions",
"name": "Smith"
},
{
"categoryid": "2",
"id": "3",
"label": "Restaurants",
"name": "KFC"
},
{
"categoryid": "2",
"id": "4",
"label": "Restaurants",
"name": "SUBWAY"
},
{
"categoryid": "2",
"id": "5",
"label": "Restaurants",
"name": "MLD"
},
{
"categoryid": "2",
"id": "6",
"label": "Restaurants",
"name": "THAI"
}, {
"categoryid": "3",
"id": "7",
"label": "Specialty Shops",
"name": "BODY SHOP"
},
]
Is there an elegant way to achieve it using underscore?
I tried to use nested _.each() to do that, but feel there might be something better.
generateArray: function(obj) {
var newResult = [];
_.each(obj.categories, function(c) {
_.each(c.Brands, function(d) {
newResult.push({
"categoryid": c.id,
"id": d.id,
"label": c.label,
"name": d.name
});
});
});
return newResult;
}
Anyone can advise me which way is more efficiency at running time?
mine or #Artyom Neustroev or #Anthony Chu ?

You don't really need underscore for that task. Use simple for .. in .. and for (...) loops:
var json = {...};
var result = [];
for (var catKey in json.shops.categories) {
var currentCategory = json.shops.categories[catKey];
for (var i = 0; i < currentCategory.Brands.length; i++) {
var currentBrand = currentCategory.Brands[i];
result.push({
categoryid: currentCategory.id,
label: currentCategory.label,
id: currentBrand.id,
name: currentBrand.name
});
}
}
Fiddle here

Instead of each()'s, here's a way to do it with map()'s...
var output = _.chain(input.shops.categories)
.map(function (category) {
return _(category.Brands).map(function (brand) {
return { categoryId: category.id,
id: brand.id,
label: category.label,
name: brand.name
};
});
}).flatten().value();
JSFIDDLE

Related

Extract the parent node name from Tree who has childrens

I want to iterate the tree and need to get the id of all the nodes which has the children in string array. while looping it is just returning me the record but doesn't extract the name of the node.
e.g const result = ['root', 'USER', 'ROLE', 'DASHBOARD', 'BRAND', 'COMPANY'];
{
"id": "root",
"name": "Roles and Permissions",
"children": [
{
"id": "USER",
"name": "USER",
"children": [
{
"id": "1",
"name": "VIEW"
},
{
"id": "2",
"name": "CREATE"
},
{
"id": "3",
"name": "EDIT"
}
]
},
{
"id": "ROLE",
"name": "ROLE",
"children": [
{
"id": "8",
"name": "VIEW"
},
{
"id": "9",
"name": "CREATE"
},
{
"id": "10",
"name": "EDIT"
},
{
"id": "11",
"name": "DELETE"
}
]
},
{
"id": "DASHBOARD",
"name": "DASHBOARD",
"children": [
{
"id": "BRAND",
"name": "BRAND",
"children": [
{
"id": "52",
"name": "VIEW"
},
{
"id": "53",
"name": "CREATE"
},
{
"id": "54",
"name": "EDIT"
},
{
"id": "55",
"name": "DELETE"
}
]
},
{
"id": "COMPANY",
"name": "COMPANY",
"children": [
{
"id": "56",
"name": "VIEW"
},
{
"id": "57",
"name": "CREATE"
},
{
"id": "58",
"name": "EDIT"
},
{
"id": "59",
"name": "DELETE"
}
]
}
]
}
]
}
I tried various looping method to get the list, e.g. but not returning the exact name of the node.
function getParent(nodes) {
if(Array.isArray(nodes.children)) {
return nodes.children.map((node) => getParent(node));
}
return nodes.name;
}
You can store the resp in an array and return that array.
const q = {
"id": "root",
"name": "Roles and Permissions",
"children": [
{
"id": "USER",
"name": "USER",
"children": [
{
"id": "1",
"name": "VIEW"
},
{
"id": "2",
"name": "CREATE"
},
{
"id": "3",
"name": "EDIT"
}
]
},
{
"id": "ROLE",
"name": "ROLE",
"children": [
{
"id": "8",
"name": "VIEW"
},
{
"id": "9",
"name": "CREATE"
},
{
"id": "10",
"name": "EDIT"
},
{
"id": "11",
"name": "DELETE"
}
]
},
{
"id": "DASHBOARD",
"name": "DASHBOARD",
"children": [
{
"id": "BRAND",
"name": "BRAND",
"children": [
{
"id": "52",
"name": "VIEW"
},
{
"id": "53",
"name": "CREATE"
},
{
"id": "54",
"name": "EDIT"
},
{
"id": "55",
"name": "DELETE"
}
]
},
{
"id": "COMPANY",
"name": "COMPANY",
"children": [
{
"id": "56",
"name": "VIEW"
},
{
"id": "57",
"name": "CREATE"
},
{
"id": "58",
"name": "EDIT"
},
{
"id": "59",
"name": "DELETE"
}
]
}
]
}
]
}
let result = []
function r(nodes){
if(Array.isArray(nodes.children)){
result.push(nodes.name);
nodes.children.map((c) => r(c))
return result;
}
return result;
}
console.log(r(q))
You can simply use a recursive function. Here ids is an array. You can initialize it before calling the function. Call this function in your getting IDs method.
const getIdFromNodesWithChild = (node) => {
if (node.children != undefined){
ids.push(node.id)
const children_list = node.children
children_list.forEach( new_child => getIdFromNodesWithChild(new_child))
}}
caller function
const returnIds = (tree) => {
ids = []
getIdFromNodesWithChild(tree)
return (ids)
}
result : ['root', 'USER', 'ROLE', 'DASHBOARD', 'BRAND', 'COMPANY']

Sorting API JSON response using Javascript

I am getting below response on hitting DoctorData.api and want to sort them all with their 'ID'. Can someone show me how to sort the Output JSON data and display it same format.
Kindly Excuse my coding skills, this is my second test case. I am new to JS.
var doctorIDgeturl = geturl.geturls.getapiUrl; //'getapiUrl' is Doctor Get API
var res = await api.getRequest(doctorIDgeturl);
logger.logger().info('GET_data = ', JSON.stringify(res.data, null, 2));
var rescount = Object.keys(res.data.data.doctorList); //doctorList is the API response object for above GET API
console.log("This is Sorted Id: ");
const sortedResponse = sort(res.data, r => r.doctorListModels.associateId, ['asc']) //using ascending order to sort
console.log(sortedResponse);
Current output:
{
"message": "Record Found",
"data": {
"DoctorsList": [
{
"id": "10",
"name": "William",
"launch_date": "2018-01-24T00:00:00.000-05:00"
},
{
"id": "2",
"name": "Snow",
"launch_date": "2017-08-14T00:00:00.000-05:00"
},
{
"id": "33",
"name": "Thomas",
"launch_date": "2018-11-29T00:00:00.000-05:00"
},
{
"id": "3",
"name": "Ismail",
"launch_date": "2018-11-29T00:00:00.000-05:00"
},
{
"id": "5",
"name": "Jackson",
"launch_date": "2018-04-10T00:00:00.000-05:00"
}
Expected output after sorting:
{
"message": "Record Found",
"data": {
"DoctorsList": [
{
"id": "2",
"name": "Snow",
"launch_date": "2017-08-14T00:00:00.000-05:00"
},
{
"id": "3",
"name": "Ismail",
"launch_date": "2018-11-29T00:00:00.000-05:00"
},
{
"id": "5",
"name": "Jackson",
"launch_date": "2018-04-10T00:00:00.000-05:00"
},
{
"id": "10",
"name": "William",
"launch_date": "2018-01-24T00:00:00.000-05:00"
},
{
"id": "33",
"name": "Thomas",
"launch_date": "2018-11-29T00:00:00.000-05:00"
}
parseInt(r.doctorListModels.associateId) or +r.doctorListModels.associateId
it seems like it sorts the id as string not number
Sorry I can't comment because of low reputation, but here is solution.
const obj = {
"message": "Record Found",
"data": {
"DoctorsList": [{
"id": "10",
"name": "William",
"launch_date": "2018-01-24T00:00:00.000-05:00"
},
{
"id": "2",
"name": "Snow",
"launch_date": "2017-08-14T00:00:00.000-05:00"
},
{
"id": "33",
"name": "Thomas",
"launch_date": "2018-11-29T00:00:00.000-05:00"
},
{
"id": "3",
"name": "Ismail",
"launch_date": "2018-11-29T00:00:00.000-05:00"
},
{
"id": "5",
"name": "Jackson",
"launch_date": "2018-04-10T00:00:00.000-05:00"
}]
}
}
const sortedResponse = obj.data.DoctorsList.sort(function(a, b) { return parseInt(a.id) - parseInt(b.id) });
console.log(sortedResponse)
const obj = {
"message": "Record Found",
"data": {
"DoctorsList": [{
"id": "10",
"name": "William",
"launch_date": "2018-01-24T00:00:00.000-05:00"
},
{
"id": "2",
"name": "Snow",
"launch_date": "2017-08-14T00:00:00.000-05:00"
},
{
"id": "33",
"name": "Thomas",
"launch_date": "2018-11-29T00:00:00.000-05:00"
},
{
"id": "3",
"name": "Ismail",
"launch_date": "2018-11-29T00:00:00.000-05:00"
},
{
"id": "5",
"name": "Jackson",
"launch_date": "2018-04-10T00:00:00.000-05:00"
}
]
}}
obj.data.DoctorsList = obj.data.DoctorsList.sort((a, b) => parseInt(a.id) > parseInt(b.id));
console.log(obj)

Get difference between two nested arrays in javascript

I wanted to get the difference between two arrays which is nested.
let firstArray = {
"family": "BLUE",
"globalThreshold": "2.0",
"levelData": [
{
"name": "India",
"value": "4.0",
"count": [
{
"id": "21",
"countName": "ABC",
"countThreshold": "7.0"
},
{
"id": "22",
"workscopeName": "DEF",
"countThreshold": "4242"
}
]
},
{
"name": "FEDERAL EXPRESS CORPORATION",
"value": "1.0",
"count": [
{
"id": "5",
"countName": "ABC",
"countThreshold": "2.0"
},
{
"id": "6",
"countName": "DEF",
"countThreshold": "3.0"
}
]
}
]
}
let changedArray= {
"family": "BLUE",
"globalThreshold": "2.0",
"levelData": [
{
"name": "India",
"value": "5",
"count": [
{
"id": "21",
"countName": "ABC",
"countThreshold": "7.0"
},
{
"id": "22",
"workscopeName": "DEF",
"countThreshold": "4242"
}
]
},
{
"name": "FEDERAL EXPRESS CORPORATION",
"value": "1.0",
"count": [
{
"id": "5",
"countName": "ABC",
"countThreshold": "60"
},
{
"id": "6",
"countName": "DEF",
"countThreshold": "3.0"
}
]
}
]
}
Expected result:
let finalArray = {
"family": "BLUE",
"globalThreshold": "2.0",
"levelData": [
{
"name": "India",
"value": "5",
"count": []
},
{
"name": "FEDERAL EXPRESS CORPORATION",
"value": "1.0",
"count": [
{
"id": "5",
"countName": "ABC",
"countThreshold": "60"
}
]
}
]
}
I would like to track the diffference based on the value property inside 'levelData' array and countThreshold inside count array.
i tried repeating two arrays in for loop but was not able to repeat Any simultaneously as its nested.Do let me know any quick approach..
Thanks
Try using map to iterate for each levelData finding their respective in firstArray by name then filter by matching its properties:
let firstArray={"family":"BLUE","globalThreshold":"2.0","levelData":[{"name":"India","value":"4.0","count":[{"id":"21","countName":"ABC","countThreshold":"7.0"},{"id":"22","workscopeName":"DEF","countThreshold":"4242"}]},{"name":"FEDERAL EXPRESS CORPORATION","value":"1.0","count":[{"id":"5","countName":"ABC","countThreshold":"2.0"},{"id":"6","countName":"DEF","countThreshold":"3.0"}]}]};
let changedArray={"family":"BLUE","globalThreshold":"2.0","levelData":[{"name":"India","value":"5","count":[{"id":"21","countName":"ABC","countThreshold":"7.0"},{"id":"22","workscopeName":"DEF","countThreshold":"4242"}]},{"name":"FEDERAL EXPRESS CORPORATION","value":"1.0","count":[{"id":"5","countName":"ABC","countThreshold":"60"},{"id":"6","countName":"DEF","countThreshold":"3.0"}]}]}
var arr = changedArray.levelData.map(ele => {
var count = firstArray.levelData.find(x => x.name == ele.name).count;
ele.count = ele.count.filter(x => !count.some(y => x.id == y.id && x.countThreshold == y.countThreshold));
return ele;
})
console.log(arr);

Build a map using values of multiple objects in an array javascript

I need to build a map "A" from an existing array of objects. However the key value pairs on Map A are from the values of existing Object keys "id" and "cap".
Is it possible to read the values of 2 keys and store as an object
var items = [{
"id": 1,
"name": "Primary",
"cap": [{
"id": "1",
"name": "1s"
}, {
"id": "2",
"name": "T2s"
}]
},{
"id": 2,
"name": "Secondary",
"cap": [{
"id": "1",
"name": "1s"
}, {
"id": "2",
"name": "T2s"
}
]
}]
My map needs to be like this
{ "1" : [{
"id": "1",
"name": "1s"
}, {
"id": "2",
"name": "T2s"
}],
"2" : [{
"id": "1",
"name": "1s"
}, {
"id": "2",
"name": "T2s"
}]
}
Use Array#reduce to achieve the results like below:
var items = [{
"id": 1,
"name": "Primary",
"cap": [{
"id": "1",
"name": "1s"
}, {
"id": "2",
"name": "T2s"
}]
}, {
"id": 2,
"name": "Secondary",
"cap": [{
"id": "1",
"name": "1s"
}, {
"id": "2",
"name": "T2s"
}]
}];
var ans = items.reduce(function(v, i) {
v[i.id] = i.cap;
return v;
}, {});
console.log(ans);
You can do this using a simple loop on the original array, and defining a new key: value pair into the object.
// Create the map
var map = {}
// For every 'item' within the 'items' array
items.forEach(item => {
// Map the item ID to the item.cap array
map[item.id] = item.cap
}
var items = [{
"id": 1,
"name": "Primary",
"cap": [{
"id": "1",
"name": "1s"
}, {
"id": "2",
"name": "T2s"
}]
}, {
"id": 2,
"name": "Secondary",
"cap": [{
"id": "1",
"name": "1s"
}, {
"id": "2",
"name": "T2s"
}]
}]
var map = {}
items.forEach(item => {
map[item.id] = item.cap
})
console.log(map)
Using ES6 Array.from() method.
var items = [{
"id": 1,
"name": "Primary",
"cap": [{
"id": "1",
"name": "1s"
}, {
"id": "2",
"name": "T2s"
}]
},{
"id": 2,
"name": "Secondary",
"cap": [{
"id": "1",
"name": "1s"
}, {
"id": "2",
"name": "T2s"
}
]
}];
var obj = {};
var res = Array.from(items, x => obj[x.id] = x.cap);
console.log(obj);

Remove an associate object while looping through using map

I have a json array and i need to delete the subarray whose id value is 5, which is falling under the serialNo 1. I tried the following method, but its not deleting any entry in the subarray.
let Details = [
{ "serialNo": "1", "text": "AAA", "subArray": [{ "id": "1", "name": "geo" }, { "id": "5", "name": "gau" }, { "id": "4", "name": "joi" }] },
{ "serialNo": "2", "text": "BBB", "subArray": [{ "id": "7", "name": "rom" }, { "id": "5", "name": "dom" }, { "id": "4", "name": "noi" }] },
{ "serialNo": "3", "text": "CCC", "subArray": [{ "id": "1", "name": "glo" }, { "id": "5", "name": "gum" }, { "id": "4", "name": "lom" }] }
];
Details.map((data) => {
if (data.serialNo === "1") {
data.subArray.map((subDetails) => {
if (subDetails.id === "5") {
delete data.subArray[subDetails];
}
})
}
})
I don't know why you explicitely wants to use the map function. But the following works:
let Details = [
{ "serialNo": "1", "text": "AAA", "subArray": [{ "id": "1", "name": "geo" }, { "id": "5", "name": "gau" }, { "id": "4", "name": "joi" }] },
{ "serialNo": "2", "text": "BBB", "subArray": [{ "id": "7", "name": "rom" }, { "id": "5", "name": "dom" }, { "id": "4", "name": "noi" }] },
{ "serialNo": "3", "text": "CCC", "subArray": [{ "id": "1", "name": "glo" }, { "id": "5", "name": "gum" }, { "id": "4", "name": "lom" }] }
];
Details = Details.map(function (data) {
if (data.serialNo === "1") {
data.subArray = data.subArray.filter(function (sa) {
return (sa.id !== "5");
});
}
return data;
});
console.log(Details);
The first problem is that you're not returning anything from the map functions. The second problem is that data.subArray[subDetails] is undefined, subDetails is an object not an index in the data.subArray array. You can use a combination of map and filter to accomplished this instead of using delete.
let Details = [
{ "serialNo": "1", "text": "AAA", "subArray": [{ "id": "1", "name": "geo" }, { "id": "5", "name": "gau" }, { "id": "4", "name": "joi" }] },
{ "serialNo": "2", "text": "BBB", "subArray": [{ "id": "7", "name": "rom" }, { "id": "5", "name": "dom" }, { "id": "4", "name": "noi" }] },
{ "serialNo": "3", "text": "CCC", "subArray": [{ "id": "1", "name": "glo" }, { "id": "5", "name": "gum" }, { "id": "4", "name": "lom" }] }
];
Details.map((data) => {
if (data.serialNo === "1") {
data.subArray = data.subArray.filter((subDetails) => {
return subDetails.id !== "5";
})
}
return data;
});
console.log(Details);
If you want to stick with map what you need to do is to return undefined when subDetails.id is 5.
let Details = [
{ "serialNo": "1", "text": "AAA", "subArray": [{ "id": "1", "name": "geo" }, { "id": "5", "name": "gau" }, { "id": "4", "name": "joi" }] },
{ "serialNo": "2", "text": "BBB", "subArray": [{ "id": "7", "name": "rom" }, { "id": "5", "name": "dom" }, { "id": "4", "name": "noi" }] },
{ "serialNo": "3", "text": "CCC", "subArray": [{ "id": "1", "name": "glo" }, { "id": "5", "name": "gum" }, { "id": "4", "name": "lom" }] }
];
Details.map((data) => {
if (data.serialNo === "1") {
data.subArray = data.subArray.filter((subDetails) => {
return subDetails.id === "5" ? undefined : subDetails;
})
}
return data;
});
console.log(Details);
One map plus object constructor:
const arr = [
{ "serialNo": "1", "text": "AAA", "subArray": [{ "id": "1", "name": "geo" }, { "id": "5", "name": "gau" }, { "id": "4", "name": "joi" }] },
{ "serialNo": "2", "text": "BBB", "subArray": [{ "id": "7", "name": "rom" }, { "id": "5", "name": "dom" }, { "id": "4", "name": "noi" }] },
{ "serialNo": "3", "text": "CCC", "subArray": [{ "id": "1", "name": "glo" }, { "id": "5", "name": "gum" }, { "id": "4", "name": "lom" }] }
];
const s = 1, id = 5; // conditions
const r = arr.map(e => (e.serialNo == s)
? Object.assign(e, {'subArray': e.subArray.filter(a => a.id != id)})
: e);
console.log(JSON.stringify(r, null, 2));
Object.assign swaps old subArray with the new filtered one.

Categories

Resources