Format data

My problem was already solved by @Paul_Wilkins here https://www.sitepoint.com/community/t/need-help-to-format-this-data/230706/2 . And I need some help again , before I have “roles, groups etc.” this time only one form of data called “events”, and I want those children will be under to the parent which is null and children whose parent value is same id of their parent. ex: “social media” and those ANC1,ANC2,ANC3 will be the children of “social media”. same also to the parent “discovery” theire children “JUST1,JUST2 and JUST3”.

please help me I’m having difficulties tweaking the code of @Paul_Wilkins but no luck.

Thank you in advance.

{
    "events": [{
        "id": 1,
        "title": "Social Media",
        "parent": null
    }, {
        "id": 2,
        "title": "ANC1",
        "parent": "1"
    }, {
        "id": 3,
        "title": "ANC2",
        "parent": "1"
    }, {
        "id": 4,
        "title": "ANC3",
        "parent": "1"
    }, {
        "id": 5,
        "title": "DISCOVERY",
        "parent": null
    }, {
        "id": 6,
        "title": "JUST1",
        "parent": "5"
    }, {
        "id": 7,
        "title": "JUST2",
        "parent": "5"
    }, {
        "id": 8,
        "title": "JUST3",
        "parent": "5"
    }]
    
}

I want to form it like this.

 [
  {
   
        "title": "Social Media",
        "children": [
          {
            "title": "ANC1",
            "key": 2
          },
          {
            "title": "ANC2",
            "key": 3
          },
          {
            "title": "ANC3",
            "key": 4
          }
        ]
      
      
    
  },
  {
   
        "title": "DISCOVERY",
        "children": [
          {
            "title": "JUST1",
            "key": 6
          },
          {
            "title": "JUST2",
            "key": 7
          },
          {
            "title": "JUST3",
            "key": 8
          }
        ]
     
  }
  
]

@Paul_Wilkins, can I ask your help again please…I have been struggling 6 days now but I could not get the desire output I want.

Thank you in advance.

I recommend that you loop through the data, from null (I suggest 0), to 1, to 2, etc, adding any matching events as you go.

I’ll be returning in a few (several) hours to see where I can go with that.

What seems to be an easier solution has been found, thanks to using some good TDD practices,

I won’t take you through it blow by blow (see an example), but the test code (that drove the development of the actual code) ended up being:

/*jslint browser */
/*global convert, describe, it, expect */
describe("convert", function () {
    "use strict";
    it("exists", function () {
        expect(convert).toBeDefined();
    });
    it("reformats an event", function () {
        var event = {"id": 1, "title": "Social Media", "parent": null};
        expect(convert([event])).toEqual([{"title": "Social Media", "key": 1}]);
    });
    it("reformats another event", function () {
        var event = {"id": 5, "title": "DISCOVERY", "parent": null};
        expect(convert([event])).toEqual([{"title": "DISCOVERY", "key": 5}]);
    });
    it("reformats multiple events", function () {
        var event1 = {"id": 1, "title": "Social Media", "parent": null, "children": []};
        var event2 = {"id": 5, "title": "DISCOVERY", "parent": null, "children": []};
        expect(convert([event1, event2])).toEqual([
            {"title": "Social Media", "key": 1},
            {"title": "DISCOVERY", "key": 5}
        ]);
    });
    it("attaches events to their parent", function () {
        var event1 = {"id": 1, "title": "Social Media", "parent": null};
        var event2 = {"id": 2, "title": "ANC1", "parent": "1"};
        var actual = convert([event1, event2]);
        var expected = [
            {"title": "Social Media", "key": 1, "children": [
                {"title": "ANC1", "key": 2}
            ]}
        ];
        expect(actual).toEqual(expected);
    });
});

The convert function that seems to achieve what you are wanting, is:

function convert(events) {
    return events.map(function (event) {
        return {
            "title": event.title,
            "key": event.id,
            "parent": event.parent
        };
    }).reduce(function (newEvents, event, ignore, oldEvents) {
        var parent;
        if (event.parent) {
            parent = oldEvents.find(function (eventParent) {
                return Number(eventParent.key) === Number(event.parent);
            });
            delete event.parent;
            if (parent) {
                parent.children = parent.children || [];
                parent.children.push(event);
            }
        } else {
            delete event.parent;
            newEvents.push(event);
        }
        return newEvents;
    }, []);
}
1 Like

Hi @Paul_Wilkins,

Thank you for the reply…I was not yet able to test this I have some problem in my internet connection it is very slow…I am still contacting my ISP…I’ll be back as soon as possible…thank you again for helping me.

Best Regards,
Jemz.

Hi @Paul_Wilkins,

My internet connection is working fine now… I test your function but it says.

event.map is not a function

please see test fiddle

Thank you in advance.

The convert function accepts an array, so give it an array.

    var treeData = convert(jsondata.events);
1 Like

Hi @Paul_Wilkins,

Thank you so much for saving my life…your the best :joy:

Hi @Paul_Wilkins,

Can I ask what kind of javascript techniques in your solution ? I was wondering why there is no loop but you get the correct output. I don’t know how the code executes.

@Paul_Wilkins,

I have problem, this is the returned data from my server. I viewed this in firebug…I apologize for my first example data. I got the wrong look up file…In the image shows I think it has 2 array of objects ?.when you collapse the [0]object, the value you can see is ,

id:1
title:"Socaila Media"
parent:null

when you collapse the [1]object, the value

id:2
title:"ANC1"
parent:1

Thank you in advance.

How is that a problem?

Hi @Paul_Wilkins,

When I tried to run, the Social Media and ANC1 are the same level.
see image

the ANSC1 should be the child of “social media”. actually your solution works if I use the first example data, but now it returns array of objects ? … I can’t format the json in firebug so that I can compare the output with the first example.

Thank you in advance.

Hi @Paul_Wilkins,

the only difference is in my table I have parent_id, but my first example is only parent, I already change your code to parent_id. but still the display is wrong.

function convert(events) {
    return events.map(function (event) {
        return {
            "title": event.title,
            "key": event.id,
            "parent": event.parent_id
        };
    }).reduce(function (newEvents, event, ignore, oldEvents) {
        var parent;
        if (event.parent_id) {
            parent = oldEvents.find(function (eventParent) {
                return Number(eventParent.key) === Number(event.parent_id);
            });
            delete event.parent_id;
            if (parent) {
                parent.children = parent.children || [];
                parent.children.push(event);
            }
        } else {
            delete event.parent_id;
            newEvents.push(event);
        }
        return newEvents;
    }, []);
}

Hi @Paul_Wilkins,

I think it’s working now I just renamed my column to parent. it display properly now. :smile:

Thank you so much.

1 Like

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.