从另一个对象中点分隔的键创建一个JavaScript对象

Create a JavaScript object from keys which are dot separated in another object

本文关键字:一个 对象 JavaScript 创建 一个对象 点分 分隔      更新时间:2023-09-26

我有一个要求,其中我有像obj={ 'a.b.c' : d }这样的对象我想把它转换成{a:{b:{c:d}}}

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

这里有一个解决方案(编辑:代码比以前更复杂,但它给出了您想要的结果,如果有什么不起作用,请告诉我):

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方法才是真正的肉。下面的两个函数只是辅助方法。

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));