Parsing json key/value data to node based data in javascript - javascript

I'm having a hard time wrapping my head around key value (which are arrays) into a node based/treemap structure. Below is some sample code to help explain.
I'd like to convert this...
// key value data
var rawData = {
"1": [],
"2": [10],
"3": [2,5,11],
"4": [],
"5": [1,7,6],
"6": [4],
"7": [],
"8": [9],
"9": [],
"10": [],
"11": []
}
to this tree map...
// tree map
var treeData = {
"id": "ALL",
"contents": [
{
"id": "3",
"contents": [
{
"id": "2",
"contents": [
{ "id": "10" }
]
}, {
"id": "5",
"contents": [
{ "id": "1" },
{ "id": "7" },
{
"id": "6",
"contents": [
{ "id": "4" }
]
}
]
},
{ "id": "11" }
]
},
{
"id": "8",
"contents": [
{ "id": "9" }
]
}
]
}
I believe some form of recursion is involved but I'm having a tough time traversing through the nodes...
var traverse = function(rawData) {
for (var i in rawData){
var datum = rawData[i];
for (var j in datum) {
if(i===datum[j]){
// tack on node to datum
}
traverse(rawData);
}
}
}

Iterating through array in not possible with for in, instead:
for (var j = 0; j < datum.length; i++) {
if(i===datum[j]){
// tack on node to datum
}
traverse(rawData);
}

Related

Count number of repetition for values in JSON nested arrays with Javascript

I'm stuck with something I thought would be easy. Let's say I have an object like this. I'm trying to insert in the div each name of the animal tagged and the number of times that tag is in types (for example, cat = 3, etc...)
var animals = '';
animals = {
"types": [
{
"id": "1",
"tags": ["cat"]
},
{
"id": "2",
"tags": ["dog"]
},
{
"id": "3",
"tags": ["cat", "bird", "dog"]
},
{
"id": "4",
"tags": []
},
{
"id": "5",
"tags": ["cat", "bird"]
}
]
}
for (var i = 0; i < animals.length; i++) {
var tags = animals[i].tags;
}
<div class="types">Number of animals:</div>
I'm a beginner with complex JSON objects, any help would be appreciated. It can be vanilla JS or Jquery.
Thanks!
Check out the snippet below, first loop iterates and counts each animal.
Second populates your div
var animals = '';
animals = {
"types": [{
"id": "1",
"tags": ["cat"]
},
{
"id": "2",
"tags": ["dog"]
},
{
"id": "3",
"tags": ["cat", "bird", "dog"]
},
{
"id": "4",
"tags": []
},
{
"id": "5",
"tags": ["cat", "bird"]
}
]
}
var tags = {};
// Iterate over all your items
animals.types.forEach(function(type) {
// Iterate over all the animals in the array
type.tags.forEach(function(tag) {
if (tag in tags) {
// If animal is present, increment the count
tags[tag] = tags[tag] + 1;
} else {
// If animal is not present, add the entry
tags[tag] = 1;
}
})
})
// Iterate over all the animals and add it to the div
for (var animal in tags) {
if (tags.hasOwnProperty(animal)) {
document.getElementsByClassName('types')[0].innerHTML += ' ' + animal + ' ' + tags[animal];
}
}
<div class="types">Number of animals:</div>
You can do like this by using map() method :
var animals = {
"types": [{
"id": "1",
"tags": ["cat"]
},
{
"id": "2",
"tags": ["dog"]
},
{
"id": "3",
"tags": ["cat", "bird", "dog"]
},
{
"id": "4",
"tags": []
},
{
"id": "5",
"tags": ["cat", "bird"]
}
]
};
var count = {};
animals.types.map(function (arr, i) {
arr.tags.map(function (tag, k) {
count[tag] = (count[tag] || 0) + 1;
});
});
console.log(count);
If you use reduce & destrucuring it becomes one liner:
var animals = {
"types": [{
"id": "1",
"tags": ["cat"]
},
{
"id": "2",
"tags": ["dog"]
},
{
"id": "3",
"tags": ["cat", "bird", "dog"]
},
{
"id": "4",
"tags": []
},
{
"id": "5",
"tags": ["cat", "bird"]
}
]
}
console.log(
animals.types.reduce((r,{tags}) => tags.map(tag => r[tag] = (r[tag] || 0) + 1) && r, {})
)
Try this simple way:
var animals = { "types": [ { "id": "1", "tags": ["cat"] }, { "id": "2", "tags": ["dog"] }, { "id": "3", "tags": ["cat", "bird", "dog"] }, { "id": "4", "tags": [] }, { "id": "5", "tags": ["cat", "bird"] } ] }
var finalRes={};
animals.types.map(function(o, i){
o.tags.map(function(p, j){
finalRes[p]=(finalRes[p]||0)+1;
});
});
console.log(finalRes);
Result:
{ cat: 3, dog: 2, bird: 2 }
Sorry, I am typing with mobile phone, slow but correct!
Flatten all tags into single array
Count each tag
Handle tag count as you need
const animals = {
"types": [
{
"id": "1",
"tags": ["cat"]
},
{
"id": "2",
"tags": ["dog"]
},
{
"id": "3",
"tags": ["cat", "bird", "dog"]
},
{
"id": "4",
"tags": []
},
{
"id": "5",
"tags": ["cat", "bird"]
},
],
};
// Flatten all tags into single array
var allTags = [].concat(
...animals.types.map(
(type) => type.tags
)
);
// Count each tag
const tagsCount = {};
allTags.forEach(
(tag) => tagsCount[tag] = tagsCount[tag] ? tagsCount[tag] + 1 : 1
)
// Handle tag count as you need
const app = document.querySelector('#app');
app.innerHTML = Object.keys(tagsCount).map((key) => {
return `<p>${key}: ${tagsCount[key]}</p>`
}).join('');
<h1>Number of Animal Types</h1>
<div id="app"></div>
Basic javascript usage.
// var animals = ''; // not needed
var animals = {
"types": [{
"id": "1",
"tags": ["cat"]
},
{
"id": "2",
"tags": ["dog"]
},
{
"id": "3",
"tags": ["cat", "bird", "dog"]
},
{
"id": "4",
"tags": []
},
{
"id": "5",
"tags": ["cat", "bird"]
}
]
};
var counts = {};
for (var i = 0; i < animals.types.length; i++) { // types is a key in animals object, animals is not an array
var tags = animals.types[i].tags;
if (tags.length > 0) {
for (var j = 0; j < tags.length; j++) {
var tag = tags[j];
if (typeof counts[tag] === 'undefined') {
counts[tag] = 0;
}
counts[tag]++;
}
}
}
console.log(counts);
You could create a hash map for all the tags and increment the count whenever you encounter that tag in that types.tags array
Then loop through the object and append that into your HTML Element
var animals = '';
animals = {
"types": [
{
"id": "1",
"tags": ["cat"]
},
{
"id": "2",
"tags": ["dog"]
},
{
"id": "3",
"tags": ["cat", "bird", "dog"]
},
{
"id": "4",
"tags": []
},
{
"id": "5",
"tags": ["cat", "bird"]
}
]
}
let types = animals.types;
var counts = {};
for (var i = 0; i < types.length; i++) {
types[i].tags.forEach((x) => {
counts[x] = (counts[x] || 0)+1;
});
}
console.log(counts);
<div class="types">Number of animals:</div>

Hierarchical json to flat with parent ID

I have Hierarchical JSON and want to convert to flat JSON without parent child.
vm.str = [
{
"s_gid": 0,
"title": "scholastic Master List 2016",
"nodes": [
{
"Id": "1",
"templateId": "1",
"s_gid": "10",
"m_s_p_id": "1",
"subject_group_name": "xxxxxxx",
"parent_id": "1",
"sname": "",
"nodes": [
{
"Id": "2",
"templateId": "1",
"s_gid": "100",
"m_s_p_id": "0",
"subject_group_name": "abc",
"parent_id": "10",
"sname": "",
"nodes": [
{
"Id": "3",
"templateId": "1",
"s_gid": "1000",
"m_s_p_id": "0",
"subject_group_name": "efg",
"parent_id": "100",
"sname": ""
}
]
}
]
}
]
}
]
what to convert to new vm.str2 = [] as flat, all nodes at same level without nodes ... sub nodes..
You can use recursive function to return one array of objects
var arr =[{"s_gid":0,"title":"scholastic Master List 2016","nodes":[{"Id":"1","templateId":"1","s_gid":"10","m_s_p_id":"1","subject_group_name":"xxxxxxx","parent_id":"1","sname":"","nodes":[{"Id":"2","templateId":"1","s_gid":"100","m_s_p_id":"0","subject_group_name":"abc","parent_id":"10","sname":"","nodes":[{"Id":"3","templateId":"1","s_gid":"1000","m_s_p_id":"0","subject_group_name":"efg","parent_id":"100","sname":""}]}]}]}]
function flatten(data) {
var result = [];
data.forEach(function(o) {
var obj = {}
for(var e in o) {
(Array.isArray(o[e])) ? result.push(...flatten(o[e])) : obj[e] = o[e];
}
result.push(obj)
})
return result;
}
console.log(flatten(arr))
You could use Array.prototype.reduce() plus recursion for this task:
function getNodes(inputArr) {
return inputArr.reduce(function (prev, value) {
return prev.concat(
[ value ],
(value.nodes ? getNodes(value.nodes) : [])
);
}, []);
}
If you still want to remove nodes, you could either use Array.prototype.map or even Array.prototype.each:
output = output.map(function (value) {
value.nodes = undefined;
return value;
});

json data retrieve by jquery

How can I get the id of info1 or info2 with each information of the inside loop by jquery loop. Fo example I want to get id 1 from info1 then all the information within id 1 similarly same as from info2. I need the output to show in the browser.
var data = {
"info1": {
"1": {
"clientname": "ruhul yahoo",
"clientemail": "ruhul080#yahoo.com",
"clientusername": "ruhulya"
},
"2": {
"clientname": "kaosar yahoo",
"clientemail": "kaosar080#yahoo.com",
"clientusername": "kaosar"
}
},
"info2": {
"3": {
"id": "24",
"receiver": "5",
"content": "chat system",
"time": "2015-08-19 12:09:19"
},
"4": {
"id": "23",
"receiver": "4",
"content": "chat system",
"time": "2015-08-19 12:09:19"
}
},
}
Thanks in advance.
Iterate the json array and access the object like the following code.
var data = {
"info1": {
"1": {
"clientname": "ruhul yahoo",
"clientemail": "ruhul080#yahoo.com",
"clientusername": "ruhulya"
},
"2": {
"clientname": "kaosar yahoo",
"clientemail": "kaosar080#yahoo.com",
"clientusername": "kaosar"
}
},
"info2": {
"3": {
"id": "24",
"receiver": "5",
"content": "chat system",
"time": "2015-08-19 12:09:19"
},
"4": {
"id": "23",
"receiver": "4",
"content": "chat system",
"time": "2015-08-19 12:09:19"
}
},
};
for(var j in data){
for(var k in data[j]){
console.log(data[j][k]);
}
}
Your browser's Console will log the following objects if you run the above example.
Object {clientname: "ruhul yahoo", clientemail: "ruhul080#yahoo.com", clientusername: "ruhulya"}
Object {clientname: "kaosar yahoo", clientemail: "kaosar080#yahoo.com", clientusername: "kaosar"}
Object {id: "24", receiver: "5", content: "chat system", time: "2015-08-19 12:09:19"}
Object {id: "23", receiver: "4", content: "chat system", time: "2015-08-19 12:09:19"}
Then you can access the values like a normal object console.log(data[j][k].clientname);
This function will find you the first instance of a variable name in the object. If you need to find a variable in a specific path you could amend this function fairly easily to do that. Certainly the function as is passes the test case you've provided.
function findVar(data, varName) {
for (var i in data) {
if (i === varName) return data[i];
if (typeof (data[i]) === 'object') {
var findResult = findVar(data[i], varName)
if (typeof(findResult) !== 'undefined')
{
return findResult;
}
}
}
return undefined;
}
Firstly, This is not a valid JSON, Rmove the last , before last {
Secondly , parse it as a JSON and get the info as
data.info1[1].clientname
var data = JSON.parse('{"info1":{"1":{"clientname":"ruhul yahoo","clientemail":"ruhul080#yahoo.com","clientusername":"ruhulya"},"2":{"clientname":"kaosar yahoo","clientemail":"kaosar080#yahoo.com","clientusername":"kaosar"}},"info2":{"3":{"id":"24","receiver":"5","content":"chat system","time":"2015-08-19 12:09:19"},"4":{"id":"23","receiver":"4","content":"chat system","time":"2015-08-19 12:09:19"}}}');
alert(data.info1[1].clientname);
alert(data.info1[2].clientname);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
You can iterate over this object like this
for(var i in data){
for(var j in data[i]){
console.log(data[i][j]);
}
}

javascript check if a key value exists in 2 JSON objects at once

I have 2 JSON objects and want to check if a value from the first one appears anywhere in the second one, and if it does, push it into an array. I've tried to write a for loop to do this, but somehow I can't seem to get it right.
Can anybody point out what I'm doing wrong?
var JSON1 = [{
"1": "1",
"2": "2"
}, {
"1": "3",
"2": "4"
}];
var JSON2 = [{
"1": "1",
"2": "2"
}, {
"1": "3",
"2": "4"
}];
var matching = [];
for (var key in JSON1) {
if(JSON2[.hasOwnProperty(JSON1[key].1) ) {
matching.push(JSON1[key].1);
}
}
console.log(matching);
Note: For numbers as key you should use obj[number] not obj.number.
var JSON1 = [{
"1": "1",
"2": "2"
}, {
"1": "3",
"2": "4"
}];
var JSON2 = [{
"1": "1",
"2": "2"
}, {
"1": "3",
"2": "4"
}];
var matching = [];
for (var key in JSON1) {
for(var k in JSON1[key]){
if(key in JSON2 && k in JSON2[key] && JSON1[key][k] == JSON2[key][k]) {
matching.push(JSON1[key][k]);
}
}
}
console.log(matching);
you can compare both by there values
var JSON1 = [{
"1": "1",
"2": "2"
}, {
"1": "3",
"2": "4"
}];
var JSON2 = [{
"1": "1",
"2": "2"
}, {
"1": "3",
"2": "4"
}];
var matching = [];
for(x in JSON1) {
for(y in JSON1[x]){
if(JSON1[x][y] == JSON2[x][y]){
matching.push(JSON1[x][y]);
}
}
}
console.log(matching);

How can this javascript object be reconstructed

I have an object type as below:
{
"1": {
"ref": "1",
"active": "1",
"showorder": "1",
"title": "Test 1"
},
"2": {
"ref": "2",
"active": "1",
"showorder": "2",
"title": "Test 2"
},
"3": {
"ref": "3",
"active": "1",
"showorder": "4",
"title": "Test 4"
},
"4": {
"ref": "4",
"active": "1",
"showorder": "9",
"title": "Test 9"
},
"5": {
"ref": "5",
"active": "1",
"showorder": "7",
"title": "Test 7"
}
}
On the basis of showorder property i need it to be arranged as follows:
{
"1": {
"ref": "1",
"active": "1",
"showorder": "1",
"title": "Test 1"
},
"2": {
"ref": "2",
"active": "1",
"showorder": "2",
"title": "Test 2"
},
"3": {
"ref": "3",
"active": "1",
"showorder": "3",
"title": "Test 3"
},
"4": {
"ref": "4",
"active": "1",
"showorder": "4",
"title": "Test 4"
},
"5": {
"ref": "5",
"active": "1",
"showorder": "5",
"title": "Test 5"
}
}
And here is my failed attempt thought i would pass the object to this function :
function reArrangeTilesObject(tilesObj){
var newObj = [];
for(var i in tilesObj){
var j = 1;
if(j == tilesObj[i].showorder){
newObj.push(tilesObj[i]);
j++;
}
}
return newObj;
}
Sorry if i am being unclear. The object is created in a random manner. So what i want is the object to be arranged as per the showorder property. so if showorder is 4 it should come in the key of 4 and not have the object of showorder 9. showorder 9 should come under the key of 9. Thanks
Steps:
Convert the object to an array (objects are unordered, arrays are ordered)
Sort the array
Code:
function reArrangeTilesObject(tilesObj) {
var tilesArray = [];
// Step 1 - convert to array
for (var i in tilesObj) {
tilesArray.push(tilesObj[i]);
}
// Step 2 - sort
tilesArray.sort(function(a, b) {
return a.showorder - b.showorder;
});
return tilesArray;
}
Result – an ordered array:
[
{"ref":"1","active":"1","showorder":"1","title":"Test 1"},
{"ref":"2","active":"1","showorder":"2","title":"Test 2"},
{"ref":"3","active":"1","showorder":"4","title":"Test 4"},
{"ref":"5","active":"1","showorder":"7","title":"Test 7"},
{"ref":"4","active":"1","showorder":"9","title":"Test 9"}
]
I may have misunderstood something but :
for (var i = 0; i < tilesObj; i++)
{
tilesObj[i].showOrder = i;
tilesObj[i].title = "Test "+i;
}
or
for (var i in tilesObj)
{
tilesObj[i].showOrder = tilesObj[i].ref;
tilesObj[i].title = "Test "+tilesObj[i].ref;
}
will do the job on the example I believe.
I can't quite understand if you're trying to rename the properties in the object array, or sort them into a new array.
If you're trying to sort:
function reArrangeTilesObject(tilesObj) {
var newObj = [];
for (var i = 1; i <= tilesObj.length; i++) {
for (var j in tilesObj) {
if (i == tilesObj[j].showorder) {
newObj.push(tilesObj[j]);
break;
}
}
}
return newObj;
}
Should add them to your newObj array based on their showorder property.
Try this one (demo):
function reArrangeTilesObject(tilesObj){
var result = {};
for(var key in tilesObj){
content = result[key] = tilesObj[key];
content.showorder = key;
content.title = "Test " + key;
}
return result;
}
It will return a new object in the original format (a Dictionary).
If you want to return an Array (and deal with possible empty indexes), just change var result = {}; into var result = [];
If you are just rewriting the showorder and title values this will work
function fix(o) {
for(var n in o) {
o[n].showorder = n;
o[n].title = "Test " + n;
}
}

Categories

Resources