【问题标题】:Create a JavaScript object from keys which are dot separated in another object从在另一个对象中以点分隔的键创建一个 JavaScript 对象
【发布时间】:2016-08-04 13:34:43
【问题描述】:

我有一个要求,我有一个像 obj={ 'a.b.c' : d } 这样的对象 我希望它转换为{a:{b:{c:d}}}

有什么方法可以在 JavaScript 中实现这一点吗?

【问题讨论】:

  • 没有{a.b.c:d}这样的对象。这是无效的语法。
  • @torazaburo 如果您创建一个空对象并使用obj[key] 语法设置属性,这是完全有效的,尽管我不明白您为什么会这样做。如果在对象声明期间将键设置为字符串,它也可以工作。
  • @kag359six 然后 OP 应该修复他的问题以将其设置为字符串,就目前而言,它是无效的语法。
  • @torazaburo 你说的没错,我修改了他的问题,目前正在审核中。

标签: javascript


【解决方案1】:

这是一个解决方案(已编辑:代码比以前更复杂,但它给出了您想要的结果,如果有问题请告诉我):

var obj = {
    'a.b.c': 22,
    'a.b.d.e': 42
}

var newObj = {};

for (var key in obj) {

    if (obj.hasOwnProperty(key)) {

        var keyList = key.split('.');
        newObj = generateNewObject(keyList, keyList.length - 1, newObj, obj[key]);

    }

}

console.log(newObj);

function generateNewObject(keys, index, existingObj, value) {

    if (index < 0) {
        return value;
    }

    var lastKey = keys[index--];
    var existingProperty = getProperty(existingObj, lastKey);

    if (existingProperty != null && !objectsAreEqual(existingProperty, value)) {

        var valueKey = keys[index + 2];
        existingProperty[lastKey][valueKey] = value[valueKey];
        value = existingProperty;


    } else {

        var subObj = {};
        subObj[lastKey] = value;
        value = subObj;
    }

    return generateNewObject(keys, index, existingObj, value);

}

function objectsAreEqual(obj1, obj2) {

    for (var key in obj1) {

        if (obj1.hasOwnProperty(key)) {

            var prop = getProperty(obj2, key);
            if (prop == null) {
                return false;
            }

        }

    }

    return true;

}

function getProperty(obj, keyDesired) {

    for (var key in obj) {

        if (obj.hasOwnProperty(key)) {

            if (key === keyDesired) {

                return obj;

            } else {

                var prop = getProperty(obj[key], keyDesired);

                if (prop != null) {
                    return prop;
                }

            }

        }

    }

    return null;

}

我不知道为什么你会有一个这样命名的对象,但是这段代码可以解决对象中的每个键的问题。这在嵌套对象(例如 {'a' : { 'b' { 'c' : {{'d' : 'e'}}}}})上无法正常工作。每次值是 JavaScript 对象时,您都必须重复 for 循环部分。

编辑

我修改了代码,使其能够识别两个属性何时相同,例如示例{ 'a.b.c' : 22 }, 'a.b.c.d.e' : 42。很抱歉,如果很难通过,但基本上generateNewObject 方法是它的真正内容。它下面的两个函数只是辅助方法。

【讨论】:

  • 他不希望{'a.b.c': 22, 'a.b.d': 42} 产生{a: {b: {c: 22, d: 42} } }吗?
  • 是的,我想要你所说的 torazaburo
  • @kag359six 感谢您的回答。这很有帮助。但是如果 torazaburo 的建议是可能的,那就完美了
  • @user1835326 查看我的修改,让我知道这是否适合您
  • @user1835326 太好了,请接受这个作为正确答案:)
【解决方案2】:

Array.reduce 在处理/转换更复杂的数据结构时通常是一个不错的选择。在考虑边缘情况的同时一般解决给定问题的方法可能类似于下一个提供的示例...

var
    d   = 'd',
    q   = 'q',

    obj = {
        'i.k.l.m.n.o.p' : q,
        'a.b.c'         : d,
        'foo'           : 'bar',
        ''              : 'empty'
    };

function parseIntoNestedTypes(type) {
    return Object.keys(type).reduce(function (collector, integralKey) {

        var
            nestedType          = collector.target,
            fragmentedKeyList   = integralKey.split('.'),
            nestedTypeRootKey   = fragmentedKeyList.shift(),
            nestedTypeEndValue  = collector.source[integralKey];

        if (fragmentedKeyList.length === 0) {

            nestedType[nestedTypeRootKey] = nestedTypeEndValue;
        } else {
            nestedType[nestedTypeRootKey] = fragmentedKeyList.reduce(function (collector, key, idx, list) {

                var
                    partialType = collector.partialType || collector.type;

                if (idx < (list.length - 1)) {

                    partialType[key] = {};
                } else {
                    partialType[key] = collector.value;
                }
                collector.partialType = partialType[key];

                return collector;

            }, {

                value : nestedTypeEndValue,
                type  : {}

            }).type;
        }
        return collector;

    }, {

        source: type,
        target: {}

    }).target;
}

console.log('parseIntoNestedTypes :: type', JSON.stringify(obj));
console.log('parseIntoNestedTypes :: nestedType', JSON.stringify(parseIntoNestedTypes(obj)));

console.log('parseIntoNestedTypes :: type, nestedType : ', obj, parseIntoNestedTypes(obj));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多