Create new javascript object from 2 JSON objects grouped by id - javascript

I have below dynamic nested JSON object arrays and I wanted to get the desired output with JavaScript grouped by id from both.
First Array:
[
{
"id": "11",
"name": "emp1",
"location": [
{ "name": "abc", "id": "lc1" }
]
},
{
"id": "11",
"name": "emp2",
"location": [
{ "name": "abc", "id": "lc1" },
]
},
{
"id": "22",
"name": "emp3",
"location": [
{ "name": "xyz", "id": "lc2" }
]
}
]
Second array like below.
[
{
"name": "sub1",
"id": "11"
...
},
{
"name": "sub1.1",
"id": "11"
...
},
{
"name": "sub2",
"id": "22"
...
}
]
Desired Output:
[
{
"id": "11",
"first": [{"name": "emp1"},
{"name": "emp2"}],
"second": [{"name": "sub1"},{"name": "sub1.1"}],
"location": [{"name": "abc"}]
},
{
"id": "22",
"first": [{"name": "emp3"}],
"second": [{"name": "sub2"}],
"location": [{"name": "xyz"}]
}
]
How to get the desired output like above using javascript/angularjs?

I would do it using the amazing Array#reduce function.
Note that I have named your first array as a1, second as a2 and result as res.
a1.reduce(function(arr, obj) {
var existing = arr.filter(function(res) {
return res.id === obj.id
})[0]
if (existing) {
existing.first.push({
name: obj.name
})
} else {
var second = a2.filter(function(res) {
return res.id === obj.id
})
var secondObj = second.length ? second.map(function(sec) {
return {
name: sec.name
};
}) : []
arr.push({
id: obj.id,
first: [{
name: obj.name
}],
second: secondObj,
location: obj.location
})
}
return arr;
}, [])
Here's the working snippet. Take a look!
var a1 = [{
"id": "11",
"name": "emp1",
"location": [{
"name": "abc",
"id": "lc1"
}]
},
{
"id": "11",
"name": "emp2",
"location": [{
"name": "abc",
"id": "lc1"
}]
},
{
"id": "22",
"name": "emp3",
"location": [{
"name": "xyz",
"id": "lc2"
}]
}
]
var a2 = [{
"name": "sub1",
"id": "11"
}, {
"name": "sub1.1",
"id": "11"
},
{
"name": "sub2",
"id": "22"
}
]
var res = a1.reduce(function(arr, obj) {
var existing = arr.filter(function(res) {
return res.id === obj.id
})[0]
if (existing) {
existing.first.push({
name: obj.name
})
} else {
var second = a2.filter(function(res) {
return res.id === obj.id
})
var secondObj = second.length ? second.map(function(sec) {
return {
name: sec.name
};
}) : []
arr.push({
id: obj.id,
first: [{
name: obj.name
}],
second: secondObj,
location: obj.location
})
}
return arr;
}, [])
console.log(res)
.as-console-wrapper {
max-height: 100% !important;
top: 0;
}

var red1 = [{
"id": "11",
"name": "emp1",
"location": [{
"name": "abc",
"id": "lc1"
}]
},
{
"id": "11",
"name": "emp2",
"location": [{
"name": "abc",
"id": "lc1"
}]
},
{
"id": "22",
"name": "emp3",
"location": [{
"name": "xyz",
"id": "lc2"
}]
}
]
var b = [{
"name": "sub1",
"id": "11"
},
{
"name": "sub2",
"id": "22"
}
]
var identication = {}
var result = []
red1.forEach(function(val) {
if (val['id'] in identication) {
var t = {}
t['name'] = val['name']
result[identication[val['id']]]['first'].push(t)
} else {
var t = {}
t['name'] = val['name']
val['first'] = []
val['first'].push(t)
delete val['name']
var identity = result.push(val)
identication[val['id']] = identity - 1;
}
})
b.forEach(function(d) {
if (d['id'] in identication) {
var t = {
'name': d['name']
}
if (!('second' in result[identication[d['id']]])) {
result[identication[d['id']]]['second'] = []
}
result[identication[d['id']]]['second'].push(t)
} else {
var t = {}
for (key in d) {
if (key == 'name')
continue
t[key] = d[key]
}
t['second'] = [{
'name': d['name']
}]
var identity = result.push(t)
identication[d['id']] = identity - 1;
}
})
console.log(result)

Related

sorting json tree with multiple property

i have prepared a json tree from a plain json. But i need to sort the tree with multiple conditions.
for example at level 1 we have multiple objects. we need to sort with level and then with a name property.
level is a number and name is an alphanumeric. so name sorting is alphabets first and then numbers
Below is the input json
var inputJson = [
{
"level": "1",
"leafFlag": "1",
"path":"p123",
"name":"food23"
},
{
"level": "1",
"leafFlag": "1",
"path":"r125",
"name":"car1"
},
{
"level": "2",
"leafFlag": "0",
"path":"p123/p345",
"name":"apple345"
},
{
"level": "2",
"leafFlag": "1",
"path":"p123/p095",
"name":"123banana"
},
{
"level": "3",
"leafFlag": "0",
"path":"p123/p095/p546",
"name":"543"
},
{
"level": "2",
"leafFlag": "1",
"path":"r125/yhes",
"name":"tata78"
}
]
var output = [];
The below code prepares the json tree.
I tried here for sorting with multiple properties
inputJson = inputJson.sort((a, b) => (parseInt(a.level) > parseInt(b.level)) ? 1 : -1)
inputJson.forEach(v => {
if (v.level == "1") {
v.children = [];
output.push(v);
}
else {
pathValues = v.path.split("/");
pathValues.pop();
var node = null;
var fullPath = "";
pathValues.forEach(p => {
fullPath = fullPath === "" ? p : fullPath + "/" + p;
node = (node == null ? output : node.children).find(o => o.path === fullPath);
})
node.children = node.children || [];
node.children.push(v);
}
})
Output from above:
var output = [
{
"level": "1",
"leafFlag": "1",
"path": "p123",
"name": "food23",
"children": [
{
"level": "2",
"leafFlag": "0",
"path": "p123/p345",
"name": "apple"
},
{
"level": "2",
"leafFlag": "1",
"path": "p123/p095",
"name": "banana",
"children": [
{
"level": "3",
"leafFlag": "0",
"path": "p123/p095/p546",
"name": "grapes"
}
]
}
]
},
{
"level": "1",
"leafFlag": "1",
"path": "r125",
"name": "car",
"children": [
{
"level": "2",
"leafFlag": "1",
"path": "r125/yhes",
"name": "tata",
"children": [
{
"level": "3",
"leafFlag": "0",
"path": "r125/yhes/sdie",
"name": "Range Rover"
}
]
},
{
"level": "2",
"leafFlag": "0",
"path": "r125/theys",
"name": "suzuki"
}
]
}
]
Expected output:
[
{
"level": "1",
"leafFlag": "1",
"path": "r125",
"name": "car",
"children": [
{
"level": "2",
"leafFlag": "0",
"path": "r125/theys",
"name": "suzuki"
},
{
"level": "2",
"leafFlag": "1",
"path": "r125/yhes",
"name": "tata",
"children": [
{
"level": "3",
"leafFlag": "0",
"path": "r125/yhes/sdie",
"name": "Range Rover"
}
]
}
]
},
{
"level": "1",
"leafFlag": "1",
"path": "p123",
"name": "food",
"children": [
{
"level": "2",
"leafFlag": "0",
"path": "p123/p345",
"name": "apple"
},
{
"level": "2",
"leafFlag": "1",
"path": "p123/p095",
"name": "banana",
"children": [
{
"level": "3",
"leafFlag": "0",
"path": "p123/p095/p546",
"name": "grapes"
}
]
}
]
}
]
I tried something like below
inputJson = inputJson.sort((a, b) => (parseInt(a.level) > parseInt(b.level)) ? 1 : -1 && a.name > b.name ? 1 ? -1)
You could take a single sort by sorting levels first and then by name.
.sort((a, b) => a.level - b.level || a.name.localeCompare(b.name))
Then build the tree with the sorted items.
var data = [{ level: "1", leafFlag: "1", path: "p123", name: "food" }, { level: "1", leafFlag: "1", path: "r125", name: "car" }, { level: "2", leafFlag: "0", path: "p123/p345", name: "apple" }, { level: "2", leafFlag: "1", path: "p123/p095", name: "banana" }, { level: "3", leafFlag: "0", path: "p123/p095/p546", name: "grapes" }, { level: "2", leafFlag: "1", path: "r125/yhes", name: "tata" }],
result = data
.sort((a, b) => a.level - b.level || a.name.localeCompare(b.name))
.reduce((r, o) => {
let p = o.path.split('/');
p.pop();
let target = p.reduce((t, _, i, p) => {
var path = p.slice(0, i + 1).join('/'),
temp = (t.children = t.children || []).find(q => q.path === path);
if (!temp) t.children.push(temp = { path }); // this is not necessary
// if all nodes are given
return temp;
}, { children: r });
(target.children = target.children || []).push({ ...o });
return r;
}, []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
var rootes= inputJson.filter(x=>x.level=='1')
for(i=0;i<rootes.length;i++){
rootes[i].children=[] }
var objwithchild = inputJson.filter(x=>x.leafFlag=='1')
for(i=0;i<objwithchild.length;i++){
objwithchild[i].children=[] }
inputJson.forEach(x=>{
patharr=x.path.split('/')
path=patharr.pop()
switch (x.level) {
case '2':
rootes.filter(p=>{if(p.path==patharr[0]){p.children.push(x)}
})
break
case '3':
objwithchild.filter(p=>{if(p.path==patharr[0]+'/'+patharr[1]){p.children.push(x)}
})
break
}
})
console.dir(rootes,{depth:null})
You should first sort by name, then re-sort the sorted array by level.
inputJson = inputJson.sort((a,b) => {return a.name > b.name}).sort((a,b) => {return (Number(a.level) - Number(b.level)};

How to convert a specified JSON object value to an array

So imagine having a JSON file like:
[
{ "name": "David", "code": "DA" },
{ "name": "Solomon", "code": "SO" },
{ "name": "Mirage", "code": "MI" }
]
How can I convert it to something like this:
['David', 'Solomon', 'Mirage']and
['DA', 'SO', 'MI]
let data = [
{ "name": "David", "code": "DA" },
{ "name": "Solomon", "code": "SO" },
{ "name": "Mirage", "code": "MI" }
];
const result = data.map(item => item.name);
const result2 = data.map(item => item.code);
console.log(result, result2);
let data = [
{ "name": "David", "code": "DA" },
{ "name": "Solomon", "code": "SO" },
{ "name": "Mirage", "code": "MI" }
];
let a1= [];
let a2= [];
data.forEach(ei =>{
a1.push(ei.name);
a2.push(ei.code);
})
console.log(a1);
console.log(a2);

Creating a new array from the parents of array child element

I have the following array
{
"id": "111",
"name": "1111",
"children": [
{
"id": "22222",
"name": "2222",
"children": [
{
"id": "AAAA",
"name": "AAAA",
"children": [
{
"id": "DDD",
"name": "DDD"
},
{
"id": "EEE",
"name": "EEE"
}
]
},
{
"id": "BBBB",
"name": "BBB",
"children": [
{
"id": "FFF",
"name": "FFF"
},
{
"id": "GGG",
"name": "GGG",
"children": [
{
"id": "7777",
"name": "7777"
},
{
"id": "8888",
"name": "8888"
}
]
}
]
}
]
}
]
}
And I would like to create an array with the parents of a child by its ID.
So for example if I wanted to get the path to the child with ID "FFF", then the array would look like something like this:
["1111", "2222", "BBB", "FFF"]
How could I go about doing that?
You could take an iterative and recursive approach.
function getItems({ children, ...object }, key, value) {
var temp;
if (object[key] === value) return [object];
if (children) children.some(o => temp = getItems(o, key, value));
return temp && [object, ...temp];
}
var data = { id: "111", name: "1111", children: [{ id: "22222", name: "2222", children: [{ id: "AAAA", name: "AAAA", children: [{ id: "DDD", name: "DDD" }, { id: "EEE", name: "EEE" }] }, { id: "BBBB", name: "BBB", children: [{ id: "FFF", name: "FFF" }, { id: "GGG", name: "GGG", children: [{ id: "7777", name: "7777" }, { id: "8888", name: "8888" }] }] }] }] };
console.log(getItems(data, 'id', 'FFF'));
.as-console-wrapper { max-height: 100% !important; top: 0; }
You could implement a recursive search to find all paths and return the correct one when you reach the desired name-value pair.
const isObject = (obj) => obj === Object(obj);
let data = loadData();
let expected = [ '1111', '2222', 'BBB', 'FFF' ];
let actual = findPath(data, 'name', 'FFF');
console.log(JSON.stringify(expected) === JSON.stringify(actual));
function findPath(data, key, value, includeIndicies=false) {
let opts = { found : null, includeIndicies : includeIndicies };
findPathInternal(data, key, value, opts, []);
return opts.found;
}
function findPathInternal(node, key, val, opts, path) {
if (Array.isArray(node)) {
for (let i = 0; i < node.length; i++) {
findPathInternal(node[i], key, val, opts, opts.includeIndicies ? path.concat(i) : path);
}
} else if (isObject(node)) {
if (node[key] === val) {
opts.found = path.concat(val); return; // Exit
} else {
let keys = Object.keys(node);
for (let i = 0; i < keys.length; i++) {
findPathInternal(node[keys[i]], key, val, opts, path.concat(node[key]));
}
}
}
};
function loadData() {
return {
"id": "111",
"name": "1111",
"children": [{
"id": "22222",
"name": "2222",
"children": [{
"id": "AAAA",
"name": "AAAA",
"children": [{
"id": "DDD",
"name": "DDD"
},
{
"id": "EEE",
"name": "EEE"
}
]
},
{
"id": "BBBB",
"name": "BBB",
"children": [{
"id": "FFF",
"name": "FFF"
},
{
"id": "GGG",
"name": "GGG",
"children": [{
"id": "7777",
"name": "7777"
},
{
"id": "8888",
"name": "8888"
}
]
}
]
}
]
}]
};
}
.as-console-wrapper { top: 0; max-height: 100% !important; }

Building new JSON from existing one

I want to build an new JSON from existing one. The source has sections and rubrics that I no longer need for a listing. The new object called 'items' should have an array of the items.
The final JSON should be sorted by attribute 'name' and look like
{
"items": [
{
"id": 10000006,
"name": "Boah"
},
{
"id": 10000013,
"name": "Gut"
},
{
"id": 10000003,
"name": "Ipsum"
},
{
"id": 10000001,
"name": "Lorem"
},
{
"id": 10000005,
"name": "Lorum"
},
{
"id": 10000004,
"name": "Name"
},
{
"id": 10000002,
"name": "Stet"
}
]
}
For building the new JSON I get this source:
{
"sections": [
{
"name": "FooBar",
"rubrics": [
{
"name": "Foo",
"items": [
{
"id": 10000001,
"name": "Lorem"
},
{
"id": 10000002,
"name": "Stet"
},
{
"id": 10000003,
"name": "Ipsum"
}
]
},
{
"name": "Bar",
"items": [
{
"id": 10000004,
"name": "Name"
},
{
"id": 10000005,
"name": "Lorum"
},
{
"id": 10000006,
"name": "Boah"
}
]
}
]
},
{
"name": "BlahBloob",
"rubrics": [
{
"name": "Bla",
"items": [
{
"id": 10000013,
"name": "Gut"
}
]
},
{
"name": "Bloob",
"items": [
{
"id": 10000014,
"name": "Name"
},
{
"id": 10000015,
"name": "Lorem"
}
]
}
]
}
]
}
What do you think? How can I do this with plain JavaScript or maybe TypeScript?
Thanks for reading and have time for my question. And thanks for reply in advance.
Here you go. You just need to iterate over each rubric of each section of your source to get the items. At the end, sort your list of items by items, and you're done.
This example uses ES6 syntax, but it's easy to convert it to ES5 if needed.
function extractItems(source) {
const items = [];
for (const section of source.sections) {
for (const rubric of section.rubrics) {
items.push(...rubric.items);
}
}
items.sort((a, b) => a.name.localeCompare(b.name));
return { items };
}
A more functional approach use map and reduce to pick the rubrics and merge them.
data.sections
.map(section => section.rubrics) // get rubrics
.reduce((a, b) => a.concat(b)) // merge rubrics
.map(rubric => rubric.items) // get items from each rubric
.reduce((a, b) => a.concat(b)) // merge items
.sort((a, b) => a.name.localeCompare(b.name)); // sort
function(oldObj) {
var newObj = {
"items": []
};
oldObj.sections.forEach(function(section) {
section.rubrics.forEach(function(rubric) {
rubric.items.forEach(function(item) {
newObj.items.push(item);
});
});
});
newObj.items = newObj.items.sort(function(a, b) {
if (a.name < b.name) { return -1; }
if (a.name > b.name) { return 1; }
return 0;
});
return newObj;
}
And simply use JSON.parse() and JSON.stringify() to convert JSON to and from objects.
It might help you
var data ={
"sections": [
{
"name": "FooBar",
"rubrics": [{"name": "Foo", "items": [{"id": 10000001,"name": "Lorem"}, {"id": 10000002,"name": "Stet"}, {"id": 10000003,"name": "Ipsum"}]
}, {
"name": "Bar",
"items": [{
"id": 10000004,
"name": "Name"
}, {
"id": 10000005,
"name": "Lorum"
}, {
"id": 10000006,
"name": "Boah"
}]
}]
}, {
"name": "BlahBloob",
"rubrics": [{
"name": "Bla",
"items": [{
"id": 10000013,
"name": "Gut"
}]
}, {
"name": "Bloob",
"items": [{
"id": 10000014,
"name": "Name"
}, {
"id": 10000015,
"name": "Lorem"
}]
}]
}]
};
var itemObj = {};
var itemArr = [];
var sections = data.sections;
for(var i=0;i<sections.length;i++)
{
for(var j=0;j<sections[i].rubrics.length;j++){
for(var k=0;k<sections[i].rubrics[j].items.length;k++){
var itemObj;
itemObj['id'] = sections[i].rubrics[j].items[k].id;
itemObj['name'] = sections[i].rubrics[j].items[k].name;
itemArr.push(itemObj);
}
}
}
var finalObj = {"items":itemArr};
console.log(finalObj);
JSFiddle

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