Home > Net >  How to map according to key on objects?
How to map according to key on objects?

Time:10-31

I'm trying to map through object values and add text if the key is right on JavaScript. Here is our object:

{
    "id": "n27",
    "name": "Thomas More",
    "className": "level-1",
    "children": [
        {
            "id": "n1",
            "name": "Rousseau",
            "className": "level-2",
            "children": [
                {
                    "id": "n2",
                    "name": "Machiavelli",
                    "className": "level-3",
                    "children": [
                        {
                            "id": "n9",
                            "name": "Edison, Thomas",
                            "className": "level-4"
                        }
                    ]
                }
            ]
        },
        {
            "id": "n3",
            "name": "Einstein",
            "className": "level-2",
            "children": [
                {
                    "id": "n10",
                    "name": "Arf, Cahit",
                    "className": "level-3",
                    "children": [
                        {
                            "id": "n15",
                            "name": "Rawls, John",
                            "className": "level-4"
                        }
                    ]
                },
                {
                    "id": "n12",
                    "name": "Smith, Adam",
                    "className": "level-3",
                    "children": [
                        {
                            "id": "n11",
                            "name": "Kant, Immanuel",
                            "className": "level-4"
                        }
                    ]
                }
            ]
        },
        {
            "id": "n60",
            "name": "Turing, Alan",
            "className": "level-2"
        }
    ]
}

I want to add " YES" to their className's. So new object should look like this:

{
    "id": "n27",
    "name": "Thomas More",
    "className": "level-1 YES",
    "children": [
        {
            "id": "n1",
            "name": "Rousseau",
            "className": "level-2 YES",
            "children": [
                {
                    "id": "n2",
                    "name": "Machiavelli",
                    "className": "level-3 YES",
                    "children": [
                        {
                            "id": "n9",
                            "name": "Edison, Thomas",
                            "className": "level-4 YES"
                        }
                    ]
                }
            ]
        },
        {
            "id": "n3",
            "name": "Einstein",
            "className": "level-2 YES",
            "children": [
                {
                    "id": "n10",
                    "name": "Arf, Cahit",
                    "className": "level-3 YES",
                    "children": [
                        {
                            "id": "n15",
                            "name": "Rawls, John",
                            "className": "level-4 YES"
                        }
                    ]
                },
                {
                    "id": "n12",
                    "name": "Smith, Adam",
                    "className": "level-3 YES",
                    "children": [
                        {
                            "id": "n11",
                            "name": "Kant, Immanuel",
                            "className": "level-4 YES"
                        }
                    ]
                }
            ]
        },
        {
            "id": "n60",
            "name": "Turing, Alan",
            "className": "level-2 YES"
        }
    ]
}

I have tried this, but it adds to all of the keys:

const addToClassName = (datasource, fn) => {
    return Object.fromEntries(Object
        .entries(datasource, fn)
        .map(([k, v]) => [k, v && v.children != undefined && v.children.length > 0 ? addToClassName(v.children, fn) : fn(v)])
    );
}

let res = addToClassName(obj, v => v   ' YEP');

How can I do it?

CodePudding user response:

You don't need to use Object.fromEntries(), instead, you make your function return a new object, with a transformed className based on the return value of fn. You can then set the children: key on the object to be a mapped version of all the objects inside of the children array. When mapping, you can pass each child into the recursive call to your addToClassName() function. You can add the children key conditionally to the output object but checking if it exists (with children &&) and then by spreading the result using the spread syntax ...:

const data = { "id": "n27", "name": "Thomas More", "className": "level-1", "children": [ { "id": "n1", "name": "Rousseau", "className": "level-2", "children": [ { "id": "n2", "name": "Machiavelli", "className": "level-3", "children": [ { "id": "n9", "name": "Edison, Thomas", "className": "level-4" } ] } ] }, { "id": "n3", "name": "Einstein", "className": "level-2", "children": [ { "id": "n10", "name": "Arf, Cahit", "className": "level-3", "children": [ { "id": "n15", "name": "Rawls, John", "className": "level-4" } ] }, { "id": "n12", "name": "Smith, Adam", "className": "level-3", "children": [ { "id": "n11", "name": "Kant, Immanuel", "className": "level-4" } ] } ] }, { "id": "n60", "name": "Turing, Alan", "className": "level-2" } ] };
const addToClassName = (obj, fn) => ({
  ...obj, 
  className: fn(obj.className), 
  ...(obj.children && {children: obj.children.map(child => addToClassName(child, fn))})
});

console.log(addToClassName(data, v => v   " YES"));
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

CodePudding user response:

If you can change the current obj object then you can achieve this using recursion as

function addClass(obj) {
  obj.className  = " YES";
  obj.children && obj.children.forEach(addClass);
}

const obj = {
  id: "n27",
  name: "Thomas More",
  className: "level-1",
  children: [
    {
      id: "n1",
      name: "Rousseau",
      className: "level-2",
      children: [
        {
          id: "n2",
          name: "Machiavelli",
          className: "level-3",
          children: [
            {
              id: "n9",
              name: "Edison, Thomas",
              className: "level-4",
            },
          ],
        },
      ],
    },
    {
      id: "n3",
      name: "Einstein",
      className: "level-2",
      children: [
        {
          id: "n10",
          name: "Arf, Cahit",
          className: "level-3",
          children: [
            {
              id: "n15",
              name: "Rawls, John",
              className: "level-4",
            },
          ],
        },
        {
          id: "n12",
          name: "Smith, Adam",
          className: "level-3",
          children: [
            {
              id: "n11",
              name: "Kant, Immanuel",
              className: "level-4",
            },
          ],
        },
      ],
    },
    {
      id: "n60",
      name: "Turing, Alan",
      className: "level-2",
    },
  ],
};

function addClass(obj) {
  obj.className  = " YES";
  obj.children && obj.children.forEach(addClass);
}

addClass(obj);
console.log(obj);
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

  • Related