简体   繁体   English

使用点表示法动态创建具有路径数组的对象

[英]Dynamically creating objects with array of paths in dot notation

I was wondering if it is possible to dynamically generate an object with an array of strings in dot notation. 我想知道是否可以用点表示法动态生成带有字符串数组的对象。 I would like to dynamically build a JSON object from a CSV file. 我想从CSV文件动态构建JSON对象。 The goal is to build the CSV as JSON, then filter the properties and make a new JSON object. 目标是将CSV构建为JSON,然后过滤属性并创建新的JSON对象。

So I would like to pass in something like this.. 所以我想传递这样的东西..

var obj = {};
var keyArray = ['meta', 'logos', 'warranty', 'specs', 'specs.engine', 'specs.engine.hp', 'specs.engine.rpm', 'specs.engine.manufacturer'];

The end result would be something like this... 最终结果将是这样的......

obj = {
 meta: {
 },
 logos: {
 },
 specs: {
    engine: {
       hp: {
       }
    }
 }
}

Here is the main function 这是主要功能

function addObjectsByKey(obj, keyArray) {

    for (var key in keyArray) {

        // If keyword is not in object notation
        if (!(keyArray[key].match(/\./))) {

            // If the object property is not set, set it
            if (!(obj[keyArray[key]])) {

                obj[keyArray[key]] = {};

            }

        } else {

            // Split array element (in dot notation) into an array of strings
           // These strings will be object properties
            var pathAsArray = keyArray[key].split('.');
            var path = null;

            for (var k in pathAsArray) {
                if (path == null) {
                    obj[pathAsArray[k]] = {};
                    path = pathAsArray[k];
                } else {
                    obj[path][pathAsArray[k]] = {};
                    path += '.' + pathAsArray[k];
                }
            }
            // throw Error('end');

        }

    }
    // return obj;
}

You can use forEach loop and inside you can split each element on . 您可以使用forEach循环,在里面可以拆分每个元素. and then use reduce method to build nested object. 然后使用reduce方法构建嵌套对象。

 var keyArray = ['meta', 'logos', 'warranty', 'specs', 'specs.engine', 'specs.engine.hp', 'specs.engine.rpm', 'specs.engine.manufacturer']; const result = {} keyArray.forEach(key => { // Loop array of keys // Split each key with . and use reduce on that // In each iteration of reduce return r[e] which is going to be value if property exists // or new object if it doesn't // This way you can go to any object depth as long as keys match existing keys in object. key.split('.').reduce((r, e) => r[e] = (r[e] || {}), result) }) console.log(result) 

Here is another approach using for loops that will return the same result. 这是使用for循环的另一种方法,它将返回相同的结果。

 var keyArray = ['meta', 'logos', 'warranty', 'specs', 'specs.engine', 'specs.engine.hp', 'specs.engine.rpm', 'specs.engine.manufacturer' ]; const result = {} for(var i = 0; i < keyArray.length; i++) { const keys = keyArray[i].split('.'); let ref = result; for(var j = 0; j < keys.length; j++) { const key = keys[j]; if(!ref[key]) ref[key] = {} ref = ref[key] } } console.log(result) 

You can use the function reduce along with a nested forEach to build the path. 您可以使用函数reduce和嵌套的forEach来构建路径。

  • The first reduce will accumulate the nested operation. 第一个reduce将累积嵌套操作。
  • The nested forEach will build the object and its children according to the current path separated by dots. 嵌套的forEach将根据以点分隔的当前路径构建对象及其子对象。

 let keyArray = ['meta', 'logos', 'warranty', 'specs', 'specs.engine', 'specs.engine.hp', 'specs.engine.rpm', 'specs.engine.manufacturer'], newObj = keyArray.reduce((accum, path) => { let previous = accum; path.split('.').forEach(key => { if (previous[key]) previous = previous[key]; else previous = previous[key] = {}; }); return accum; }, {}); console.log(newObj); 
 .as-console-wrapper { max-height: 100% !important; top: 0; } 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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