简体   繁体   中英

How to recursively objectify a string

While trying to become more comfortable with recursive functions, I attempted to write a function that takes a dot-separated string and converts that into an object. So, given the following string: user.first.name.robert this function should return the following object:

{
  user: {
    first: {
      name: 'robert'
    }
  }
}

Here's my attempt:

function objectifyHelper(array, object) {
    if (array.length === 2) {
        const [key, value] = array;
        object[key] = value;
        return object;
    } else {
        object[array[0]] = objectifyHelper(array.slice(1), object); 
        return object;
    }
}

function objectify(string) {
    const tokens = string.split('.');
    return objectifyHelper(tokens, {});
}

const str = 'user.first.name.robert';
const result = objectify(str);

This gets me the following result:

result <ref *1> {
  name: 'robert',
  first: [Circular * 1],
  user: [Circular * 1]
}

What am I doing wrong?

You're only ever creating a single object here:

return objectifyHelper(tokens, {});

that then gets used every time a property is assigned to it. You need to instead create a new object when recursing, and not only inside of objectify .

A simpler approach would be:

 const objectify = string => string .split('.') .reduceRight( (innerObj, prop) => ({ [prop]: innerObj }) ); const str = 'user.first.name.robert'; const result = objectify(str); console.log(result);

You are almost there. However, if your helper accepts an object but also returns it, be consistent in your recursive call

 function objectifyHelper(array, object) { if (array.length === 2) { const [key, value] = array; object[key] = value; return object; } else { object[array[0]] = objectifyHelper(array.slice(1), {}); return object; } } function objectify(string) { const tokens = string.split('.'); return objectifyHelper(tokens, {}); } const str = 'user.first.name.robert'; const result = objectify(str); console.log(result)

Note that this only changes your

object[array[0]] = objectifyHelper(array.slice(1), object); 

to

object[array[0]] = objectifyHelper(array.slice(1), {}); 

Reading OP's comment under the question, I believe it's fair to further expand the answer.

Yes, passing the newly created object to the recursive function and then returning it is could be simplified. One of possible approaches would be to remove the need to pass the object into the function and just return a newly created object to the caller.

Thus, a simplified version would be

 function objectifyHelper(array) { // we always create a new object var object = {}; if (array.length === 2) { const [key, value] = array; object[key] = value; } else { object[array[0]] = objectifyHelper(array.slice(1)); } // and return it return object; } function objectify(string) { const tokens = string.split('.'); return objectifyHelper(tokens); } const str = 'user.first.name.robert'; const result = objectify(str); console.log(result);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM