将具有'long.property.name'属性的对象转换为树对象

时间:2017-04-26 19:00:32

标签: javascript object underscore.js lodash

我想转换这样的对象:

foo = {
    42: 'foo', 
    'a.b.c[0].42': 'bar',
    'a.b.c[0].43': 'zet',
    'a.d.c[0].42': 'baz'
}

要:

bar = {
    42: 'foo',
    'a.b.c[0].42': 'bar',
    'a.b.c[0].43': 'zet',
    'a.d.c[0].42': 'baz',
    a: {
        b: {
            c: [{
                42: 'bar', 43: 'zet'
            }]
        },
        d: {
            c: [{
                42: 'baz'
            }]
        }
    }
}

有人知道如何实现convertToTree功能吗? 我们在项目中使用lodash,这样可以帮助完成基本操作。

var object = {
    42: "foo", 
    "a.b.c[0].42": "bar",
    "a.b.c[0].43": "zet",
    "a.d.c[0].42": "baz"
};

function convertToTree() {
  // code here
}
        
convertToTree(object) === {
  "42": "foo",
  "a.b.c[0].42": "bar",
  "a.b.c[0].43": "zet",
  "a.d.c[0].42": "baz",
  "a": {
    "b": {
      "c": [
        {
          "42": "bar",
          "43": "zet"
        }
      ]
    },
    "d": {
      "c": [
        {
          "42": "baz"
        }
      ]
    }
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.js"></script>

UPD:

我需要在另一个代码处进行此类操作的转换:

_.result(bar, 'a.b.c[0].42') === 'bar'

您可以找到_.result功能说明here

3 个答案:

答案 0 :(得分:1)

您需要为数字索引使用自定义函数,因为lodash将所有数字和数字视为字符串作为数字。它产生稀疏元素,这里不需要它。

function setValue(object, path, value) {
    var last = path.pop();
    path.reduce(function (o, k, i, kk) {
        return o[k] = o[k] || (typeof (i + 1 in kk ? kk[i + 1] : last) === 'number' ? [] : {});
    }, object)[last] = value;
}

var foo = { 42: 'foo', 'a.b.c[0].42': 'bar', 'a.b.c[0].43': 'zet', 'a.d.c[0].42': 'baz' },
    bar = {};

Object.keys(foo).forEach(function (k) {
    setValue(bar, k.split(/\.|(?=\[)/).map(function (v) { return v.match(/^\[.+\]$/) ? +v.slice(1, -1) : v; }), foo[k]);
});

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

与lodash比较

var foo = { 42: 'foo', 'a.b.c[0].42': 'bar', 'a.b.c[0].43': 'zet', 'a.d.c[0].42': 'baz' },
    keys = Object.keys(foo),
    bar = _.zipObjectDeep(keys, keys.map(function (k) { return foo[k]; }));

console.log(bar);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.min.js"></script>

答案 1 :(得分:1)

这是一个很小的库:https://github.com/richie5um/flattenjs

console.log(flattened);
// {
//     'a': true,
//     'b.bb[0]': 0,
//     'b.bb[1]': 1,
//     'b.bb[2]': 2,
//     'b.bb[3]': 3,
//     'b.bb[4]': 4
// }

unflattened = FlattenJS.undo(flattened);
console.log(unflattened);
// { a: true, b: { bb: [ 0, 1, 2, 3, 4 ] } }

答案 2 :(得分:0)

我的解决方案基于@ mik01aj答案。

var rawObject = {
    42: "foo", 
    "a.b.c[0].42": "bar",
    "a.b.c[0].43": "zet",
    "a.d.c[0].42": "baz"
};

function convertToTree(rowObjectData) {
  return _.assign(
      {}, 
      rowObjectData, 
      _.reduce(rowObjectData, function (result, value, key) { 
          return _.set(result, key, value); 
      }, {}))
}

var convertedObject = convertToTree(rawObject);
        
console.log(_.result(convertedObject, "a.b.c[0].42") === "bar");
console.log(convertedObject["a.b.c[0].42"] === "bar");
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.js"></script>