递归重命名对象键

时间:2013-11-03 11:39:26

标签: javascript jquery recursion multidimensional-array

我有一个递归函数来重命名对象的键名,但是我无法弄清楚如何重命名2个键(问题键是对象)

我认为问题出在我正在检查对象类型但是如何在那时重命名密钥?

实际数组非常大,但下面是一个减少版本。

任何帮助表示感谢。

var keys_short = ['ch','d','u','tz'];
var keys_long = ['children','data','user_id','time_zone'];
function refit_keys(o){
    build = {};
    for (var i in o){
        if(typeof(o[i])=="object"){
            o[i] = refit_keys(o[i]);
            build = o;
        }else{
            var ix = keys_short.indexOf(i);
            if(ix!=-1){
                build[keys_long[ix]] = o[keys_short[ix]];
            }
        }
    }
    return build;
}

我的输入如下:

{
    "id":"1",
    "ch":[
        {
            "id":"3",
            "ch":[
            ],
            "d":{
                "u":"3",
                "tz":"8.00"
            }
        },
        {
            "id":"45",
            "ch":[
                {
                    "id":"70",
                    "ch":[
                        {
                            "id":"43",
                            "ch":[
                            ],
                            "d":{
                                "u":"43",
                                "tz":"-7.00"
                            }
                        }
                    ],
                    "d":{
                        "u":"70",
                        "tz":"-7.00"
                    }
                }
            ],
            "d":{
                "u":"45",
                "tz":"-7.00"
            }
        }
    ],
    "d":{
        "u":"1",
        "tz":"8.00"
    }
}

我的输出如下:

{
    "id":"1",
    "ch":[
        {
            "id":"3",
            "ch":[
            ],
            "d":{
                "user_id":"3",
                "time_zone":"8.00"
            }
        },
        {
            "id":"45",
            "ch":[
                {
                    "id":"70",
                    "ch":[
                        {
                            "id":"43",
                            "ch":[
                            ],
                            "d":{
                                "user_id":"43",
                                "time_zone":"-7.00"
                            }
                        }
                    ],
                    "d":{
                        "user_id":"70",
                        "time_zone":"-7.00"
                    }
                }
            ],
            "d":{
                "user_id":"45",
                "time_zone":"-7.00"
            }
        }
    ],
    "d":{
        "user_id":"1",
        "time_zone":"8.00"
    }
}

4 个答案:

答案 0 :(得分:7)

那里有几个问题。

一个是因为你未能在函数中声明build变量而成为The Horror of Implicit Globals的牺牲品。

但逻辑也存在问题,这里是最小的改造:

var keys_short = ['ch','d','u','tz'];
var keys_long = ['children','data','user_id','time_zone'];
function refit_keys(o){
    var build, key, destKey, ix, value;

    build = {};
    for (key in o) {
        // Get the destination key
        ix = keys_short.indexOf(key);
        destKey = ix === -1 ? key : keys_long[ix];

        // Get the value
        value = o[key];

        // If this is an object, recurse
        if (typeof value === "object") {
            value = refit_keys(value);
        }

        // Set it on the result using the destination key
        build[destKey] = value;
    }
    return build;
}

Live Example | Source

但是我建议使用键映射而不是并行数组:

var mapShortToLong = {
    "ch": "children",
    "d":  "data",
    "u":  "user_id",
    "tz": "time_zone"
};
function refit_keys(o){
    var build, key, destKey, ix, value;

    build = {};
    for (key in o) {
        // Get the destination key
        destKey = mapShortToLong[key] || key;

        // Get the value
        value = o[key];

        // If this is an object, recurse
        if (typeof value === "object") {
            value = refit_keys(value);
        }

        // Set it on the result using the destination key
        build[destKey] = value;
    }
    return build;
}

Live Example | Source

答案 1 :(得分:2)

问题之一可能是变量build实际上是一个全局变量。因此,它只包含递归中第一个深度的结果。

var之前添加build应解决部分问题。

答案 2 :(得分:2)

有点晚了,但是我一直在寻找一个不错的简短实现,它也可以处理数组(前面的答案没有),所以我决定发布我的通用ES6实现,因为它可能帮助一些人:

function deepMapKeys(originalObject, callback) {
  if (typeof originalObject !== 'object') {
    return originalObject
  }

  return Object.keys(originalObject || {}).reduce((newObject, key) => {
    const newKey = callback(key)
    const originalValue = originalObject[key]
    let newValue = originalValue
    if (Array.isArray(originalValue)) {
      newValue = originalValue.map(item => deepMapKeys(item, callback))
    } else if (typeof originalValue === 'object') {
      newValue = deepMapKeys(originalValue, callback)
    }
    return {
      ...newObject,
      [newKey]: newValue,
    }
  }, {})
}

对于有问题的案例,电话为:

deepMapKeys(inputObject, key => (keys_long[keys_short.indexOf(key)] || key))

话虽如此,如果您可以使用npm,那么这里有几个软件包(这里是oneanother ..)

答案 3 :(得分:0)

我喜欢这种方法。但是我偶然发现了这一点:

您这样称呼它:deepMapKeys({testValue:["justString"]}, key => (key));

returnValue包含:

{0: "j", 1: "u", 2: "s", 3: "t", 4: "S", 5: "t", 6: "r", 7: "i", 8: "n", 9: "g"}

长度:1

会说,它将我的字符串转换为数组。