最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

lodash - Splitting dots into separate objects javascript - Stack Overflow

programmeradmin1浏览0评论

I have an object like this:

var data = {"prop.health": 1, "prop.cost":1, "prop.time":1}

I want to change it into an object like this:

{
  "prop": {
    "health": 1, 
    "cost":1, 
    "time":1
  }
}

Here's my code:

  _.each(data, function (value, key) {
    var split = key.split('.')
    if (split.length > 1) {
      data[split[0]] = data[split[0]] || {}
      data[split[0]][split[1]] = value
      delete data[key]
    }
  })

But this only works for 1 level of nesting. How would you write it to ensure it works for as deeply nested properties as you need?

I have an object like this:

var data = {"prop.health": 1, "prop.cost":1, "prop.time":1}

I want to change it into an object like this:

{
  "prop": {
    "health": 1, 
    "cost":1, 
    "time":1
  }
}

Here's my code:

  _.each(data, function (value, key) {
    var split = key.split('.')
    if (split.length > 1) {
      data[split[0]] = data[split[0]] || {}
      data[split[0]][split[1]] = value
      delete data[key]
    }
  })

But this only works for 1 level of nesting. How would you write it to ensure it works for as deeply nested properties as you need?

Share Improve this question edited Nov 12, 2015 at 1:02 Harry asked Nov 12, 2015 at 0:54 HarryHarry 55.1k76 gold badges187 silver badges270 bronze badges 8
  • 2 How does nested look? prop.test.fun?? – epascarello Commented Nov 12, 2015 at 0:56
  • 1 @epascarello {'prop':{'test': {'fun': 1}}} – Harry Commented Nov 12, 2015 at 1:01
  • Is that underscore or lodash you are using? – AtheistP3ace Commented Nov 12, 2015 at 1:01
  • @AtheistP3ace lodash – Harry Commented Nov 12, 2015 at 1:01
  • 2 @RensTillmann I've used to before to keep client side view models synced with a server side object and just had it pass the object path and value down to me and from that server side path update my client side view model. – AtheistP3ace Commented Nov 12, 2015 at 1:09
 |  Show 3 more ments

3 Answers 3

Reset to default 8

You can use a bination of _.transform and _.set, for example

data = _.transform(data, function(transformed, val, key) {
    _.set(transformed, key, val);
});

Results in

{"prop":{"health":1,"cost":1,"time":1}}

Without a library it would be something like this:

(function(){
    var data = {"prop.health": 1, "prop.cost":1, "prop.time":1, "prop.test.fun" : 1, "prop.test.sun" : 1};
    var obj = {};  //will hold the object all parsed out
    Object.keys(data).forEach( function (key) {  //loop through the keys in the object
        var val = data[key];  //grab the value of this key
        var step = obj;  //reference the object that holds the values
        key.split(".").forEach(function(part, index, arr){   //split the parts and loop
            if(index===arr.length-1){  //If we are at the last index, than we set the value
                step[part] = val;
            } else if(step[part]===undefined) {  //If we have not seen this key before, create an object
                step[part] = {};
            }
            step = step[part];  //Step up the object we are referencing 
        });
    } );
    console.log(obj);
}());

Or the double reduce loop

(function(){
    var data = {"prop.health": 1, "prop.cost":1, "prop.time":1, "prop.test.fun" : 1, "prop.test.sun" : 1};
    var result = Object.keys(data).reduce( function (obj, key) {  //loop through the keys in the object
        var val = data[key];  //grab the value of this key
        key.split(".").reduce(function(step, part, index, arr){   //split the parts and loop
            if(index===arr.length-1){  //If we are at the last index, than we set the value
                step[part] = val;
            } else if(step[part]===undefined) {  //If we have not seen this key before, create an object
                step[part] = {};
            }
            return step[part];  //Step up the object we are referencing
        }, obj);
        return obj;
    }, {});
    console.log(result);
}());

Depending on a number of factors (e.g. if the original object always has keys you want to delete, etc.) you may be able to use _.set:

var data = {"prop.health": 1, "prop.cost":1, "prop.time":1};

_.each(data, function (value, key) {
  delete data[key];
  _.set(data, key, value);
});

_.set will create the path if it doesn't exist. The above results in:

{"prop":{"health":1,"cost":1,"time":1}}

And {"prop.health": 1, "prop.cost.food":1, "prop.time":1} will result in:

{"prop":{"health":1,"cost":{"food":1},"time":1}}
发布评论

评论列表(0)

  1. 暂无评论