0

I'd like to create a tree of services from a string which are properties of people. I manage to do it, but the code is quite ugly, and it's a king of practice for me for the trick is i'd like to make it with "class" of objects using "Object.create()" where the class would look like this :

let service = {
        serviceFather: "",
        serviceChildren: [],
        people: [],
        }
    }; 

A sample of input is :

[
  {
    "name": "John Doe",
    "service": "EE",
  },
  {
    "name": "Jane Doe",
    "service": "EE.EA",
  },
  {
    "name": "Jack Smith",
    "service": "EE.EA.EB",
  },
  {
    "name": "Jill Smith",
    "service": "EE.EA.EC"
  },
  {
    "name": "Jake Smith",
    "serviceLevel": "EE.EA.EC"
  }
]

The expected output would be :

[
{
    "name": "EE",
    "serviceFather": "root",
    "people": [
    {
        "name": "John Doe"
    }],
    "serviceChildren": [
    {
        "name": "EA",
        "serviceFather": "EE",
        "people": [
        {
            "name": "Jane Doe"
        }],
        "serviceChildren": [
        {
            "name": "EB",
            "serviceFather": "EA",
            "people": [
            {
                "name": "Jack Smith"
            }],
            "sousService": ""
        },
        {
            "name": "EC",
            "serviceFather": "EA",
            "people": [
            {
                "name": "Jill Smith"
            },
            {
                "name": "Jake Smith"
            }],
            "sousService": ""
        }]
    }]
}]
10
  • 3
    please add your try and what goes wrong. btw service !== serviceLevel as key. Commented Mar 21, 2019 at 10:45
  • 1
    The expected output would be why? whats the logic? Commented Mar 21, 2019 at 10:47
  • @JaromandaX : the goal is to make a tree of services... the expected output looks like a tree of services. What is not logical ? Commented Mar 21, 2019 at 10:57
  • Can you have more than one service: "EE" ... can you have more than one root level service, e.g. service: "FF"? if so, is it valid to have an EE.EA and an FF.EA for example? and finally, have you written a single line of code yourself? Commented Mar 21, 2019 at 11:00
  • @NinaScholz my try has not made anythink near the goal. The thing is i don't really get how i can check the existence of an object created this way. for example : let services = obj.service.split("."); for (let i = 0; i < obj.services.length); i++) {if (this.name !== services[i]) {let newService = Object.create(service)} else {????}} Commented Mar 21, 2019 at 11:02

2 Answers 2

1

You could use split on service property and then forEach loop and reduce to iterate nested tree and add to array.

const data = [{ "name": "John Doe", "service": "EE" }, { "name": "Jane Doe", "service": "EE.EA" }, { "name": "Jack Smith", "service": "EE.EA.EB" },
  { "name": "Jill Smith", "service": "EE.EA.EC" }, { "name": "Jake Smith", "service": "EE.EA.EC" }
]

let service = {
  serviceFather: "",
  serviceChildren: [],
  people: [],
};

function create(data) {
  const res = []
  data.forEach(obj => {
    obj.service.split('.').reduce((r, e, i, a) => {
      const match = r.find(({ name }) => name == e);
      if(!match) {
        const o = Object.create(service);
        o.name = e;
        o.serviceFather = (i == 0 ? 'root' : a[i - 1])
        o.people = [{ name: obj.name }]
        o.serviceChildren = [];
        r.push(o)
        return r;
      } else {
        if(!a[i + 1]) match.people.push({ name: obj.name })
        return match.serviceChildren
      }
    }, res)
  })
  return res;
}

const result = create(data)
console.log(result)

Sign up to request clarification or add additional context in comments.

3 Comments

damn! sure... simplest things are mostly often the best ones!!! thank you!
smthg went wrong. there s 2 divisions in which some grand children have the same "name" in each division. So the grand children of the second division went to the the first division... i think we should take another property to build the tree.
1

You could take a dummy object and iterate the service levels.

var data = [{ name: "John Doe", service: "EE" }, { name: "Jane Doe", service: "EE.EA" }, { name: "Jack Smith", service: "EE.EA.EB" }, { name: "Jill Smith", service: "EE.EA.EC" }, { name: "Jake Smith", service: "EE.EA.EC" }],
    result = [];

data.forEach(({ name, service }) => {
    service
        .split('.')
        .reduce((o, k, i, a) => {
            var temp = (o.serviceChildren = o.serviceChildren || []).find(({ name }) => name === k);
            if (!temp) {
                o.serviceChildren.push(temp = {
                    name: k,
                    serviceFather: a[i - 1] || 'root',
                    people: []
                });
            }
            return temp;
        }, { serviceChildren: result })
        .people.push({ name });
});

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

1 Comment

Thank you. This is a way to solve it, even if i was looking for the way to use "classes". :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.