1

I'm new to programming, and I was working a question which is bother me for a while.

I want to recursively create a nested object from another nested object in javascript,

below is the sample data for input, but in real situation, I don't how deep will this object to be.

nums = {
    Obj:{
        x1:{
            x11:43,
            x12:4,
            x13:612
        },
        x2:{
            x21:4,
            x22:7,
        },
        x3:2,
    }}

this is the result I want (see number is even or odd, even=true, odd=false)

res = {
    Obj:{
        x1:{
            x11:false,
            x12:true,
            x13:true
        },
        x2:{
            x21:true,
            x22:false,
        },
        x3:true,
    }}

and this is my code

const nums = {
    Obj:{
        x1:{
            x11:43,
            x12:4,
            x13:612
        },
        x2:{
            x21:4,
            x22:7,
        },
        x3:2,
    }
}
const res ={};

getResult(nums);

console.log(res);

function getResult(x){
    Object.keys(x).forEach(element => {
        if(isNaN(x[element])){
            res[element]=getResult(x[element]);
        } else {
            let result = (x[element] % 2 < 1)? true:false;
            return {[element]: result}; // this is where I don't know what to, I try to return a object, 
                                        //  but it gives{x1: undefined, x2: undefined, Obj: undefined}
                                        //
                                        // if I change to "return res[element]=result"
                                        // every sub-Object will add under the same level
        }
    });
}

I will really appreciate if someone can help me on this.

3 Answers 3

1

Instead of return {[element]: result}; , overwrite the value, and return the mutated object from the function after the loop :

note that this will mutate the original object, if you want to keep it, make a copy :

const copy = JSON.parse(JSON.stringify(nums));

const nums = {
  Obj: {
    x1: {
      x11: 43,
      x12: 4,
      x13: 612
    },
    x2: {
      x21: 4,
      x22: 7,
    },
    x3: 2,
  }
}
const res = {};
const copy = JSON.parse(JSON.stringify(nums));

getResult(copy);

console.log(res);

function getResult(x) {
  Object.keys(x).forEach(element => {
    if (isNaN(x[element])) {
      res[element] = getResult(x[element]);
    } else {
      let result = (x[element] % 2 < 1) ? true : false;
      x[element] = result; // overwrite the number with true or flse
    }
  });
  return x; // return the mutated object
}

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

Comments

1

Instead of mutating something make something more functional and return a new object:

const getResults = o => typeof o === "object"
    ? Object.keys(o).reduce((a, k) => ({ ...a, [k]: getResults(o[k]) }), {})
    : o % 2 === 1;

Basically we check if object is an object (using typeof) and go deeper if so. Otherwise we check if it is odd or even.

Comments

1

You can also think of this more generically, writing a function that will apply your transformation to all the leaf nodes of your object, then calling it with an isEven function. Here's one technique:

const mapLeaves = (fn) => (tree) =>
  typeof tree == "object"
    ? Object .fromEntries (Object .entries (tree) .map (
        ([k, v]) => [k, mapLeaves (fn) (v)]
      ))
    : fn (tree)
 
const isEven = (n) => n % 2 == 0

const nums = {Obj: {x1: {x11: 43, x12: 4, x13: 612}, x2: {x21: 4, x22: 7}, x3: 2}}

console .log (
  mapLeaves (isEven) (nums)
)

And of course mapLeaves (isEven) is a reusable function that you could apply to multiple objects.

This does not handle arrays. It would only be slightly more complex to create a version of mapLeaves that also applied this to entries of an array:

const mapLeaves = (fn) => (tree) =>
  Array .isArray (tree)
    ? tree .map (x => mapLeaves (fn) (x))
  : typeof tree == "object"
    ? Object .fromEntries (Object .entries (tree) .map (
        ([k, v]) => [k, mapLeaves (fn) (v)]
      ))
  : fn (tree)

Comments

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.