KieSun / all-of-frontend

你想知道的前端内容都在这

Home Page:https://yuchengkai.cn/docs/frontend

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

第九题:修改嵌套层级很深对象的 key

KieSun opened this issue · comments

commented

有一个嵌套层次很深的对象,key 都是 a_b 形式 ,需要改成 ab 的形式,注意不能用递归

const a = {
  a_y: {
    a_z: {
      y_x: 6
    },
    b_c: 1
  }
}
// {
//   ay: {
//     az: {
//       yx: 6
//     },
//     bc: 1
//   }
// }

去答题

新建了一个大厂真题每日打卡群,有意愿学习打卡的再进,群已达扫码上线,请加好友拉你进群

CODING

  const changeKey = (obj) => {
    let objValueKey = [obj];
    while (objValueKey.length) {
      objValueKey.forEach((item, index) => {
        objValueKey.splice(index, 1);
        for (let item2 in item) {
          if (Object.prototype.toString.call(item[item2]) === "[object Object]") {
            objValueKey.push(item[item2]);
          }
          item[item2.replace(/_/, "")] = item[item2];
          delete item[item2];
        }
      });
    }
    return obj;
  }


  const a = {
    a_y: {
      a_z: {
        y_x: 6
      },
      b_c: 1
    }
  };
  
  console.time('耗时');
  console.log(changeKey(a));
  console.timeEnd('耗时');

Edit https://github.com/KieSun/fucking-frontend/issues/14

image

Typescript 实现 👋

方法一:递归

type DeepTypeOrString<T> = {
  [K in keyof T]: DeepTypeOrString<T[K]>;
};
type Recursion = <T>(obj: DeepTypeOrString<T>) => DeepTypeOrString<T>;

const recursion: Recursion = (obj) => {
  const keys = Object.keys(obj);
  keys.forEach((key) => {
    const newKey = key.replace(/_/g, "");
    obj[newKey] = recursion(obj[key]);
    delete obj[key];
  });
  return obj;
};

console.log(recursion(a));

方法二:序列化 JSON.stringify + 正则匹配

type DeepTypeOrString<T> = {
  [K in keyof T]: DeepTypeOrString<T[K]>;
};
type RegularExpress = <T>(obj: DeepTypeOrString<T>) => DeepTypeOrString<T>;

const regularExpress: RegularExpress = (obj) => {
  try {
    const regExp = /_/g;
    const str = JSON.stringify(obj).replace(regExp, "");
    return JSON.parse(str);
  } catch (error) {
    return obj;
  }
};;

Edit 8-uobject-keypdate

commented
function dfs(data) {
  const obj = {};
  for (let i in  data) {
      let key = `${i.slice(0, 1)}${i.slice(2, 3)}`;
      if (data[i] instanceof Object) {
        obj[key] = dfs(data[i]);
      } else {
        obj[key] = data[i];
      }
  }
  return obj;
};
const a = {
  a_y: {
    a_z: {
      y_x: 6
    },
    b_c: 1
  }
}
console.log(dfs(a));
// { ay: { az: { yx: 6 }, bc: 1 } }
// 方法2  迭代
function dfs(data) {
  let arr = [data];
  while (arr.length != 0) {
      const target = arr.pop();
      change(target); // 对对象里的数据进行名称转化
      if (target instanceof Object) { // 如果是对象的话,继续将他的属性加进去
        for (let i in target) {
          arr.push(target[i]);
        }
      }
  }
  console.log(data);
  return data;
};
const change = (data) => {
  const key = Object.keys(data);
  const reg = /\_/g;
  for (let i = 0; i < key.length; i++) {
    let tempKey = key[i].replace(reg, '');
    data[tempKey] = data[key[i]];
    delete data[key[i]];
  }
};
const a = {
  a_y: {
    a_z: {
      y_x: 6,
      z_j: 7,
    },
    b_c: 1
  }
}
dfs(a)

//{ ay: { az: { yx: 6, zj: 7 }, bc: 1 } }
const a = {
    a_y: {
        a_z: {
            y_x: 6
        },
        b_c: 1
    }
}

const parseKey = (obj) => {
    try {
        const reg = /(\w+)_(\w+)":/g
        return JSON.parse(JSON.stringify(obj).replace(reg, (match) => match.replace('_', '')))
    } catch (error) {
        return obj
    }
}

console.log(parseKey(a))

类似的题目:遍历DOM节点
可参考:https://segmentfault.com/a/1190000018706578

方法一:深度优先遍历(递归)

  • 缺点:对象层级很深的时候调用栈会很深,导致 stack overflow
  • 此外,按照题目意思应该是修改原对象,频繁调用delete,对V8很不友好(涉及到隐藏类的转换)
function dfs(obj, list) {
    if (!obj) return
    for (let key in obj) {
        if (typeof obj[key] === 'object' && obj[key] !== null) {
            list.push(obj[key])
            dfs(obj[key], list)
        }
    }
    return list
}

function transformKeys(obj) {
    const list = []
    dfs(obj, list)

    list.forEach(item => {
        for (let key in item) {
            const newKey = key.replace(/_/i, '')
            item[newKey] = item[key]
            delete item[key]
        }
    })
}

transformKeys(a)

方法二:深度优先遍历(非递归)

function dfs(obj) {
    const list = []
    if (!obj) return list
    const stack = []
    stack.push(obj)
    while (stack.length) {
        let item = stack.pop()
        for (let key in item) {
            if (typeof item[key] === 'object' && item[key] !== null) {
                list.push(item[key])
                stack.push(item[key])
            }
        }
    }
    return list
}

function transformKeys(obj) {
    const list = dfs(obj)

    list.forEach(item => {
        for (let key in item) {
            const newKey = key.replace(/_/i, '')
            item[newKey] = item[key]
            delete item[key]
        }
    })
}

transformKeys(a)

方法三:深度优先遍历的另一种形式(递归)

function transformKeys(obj) {
    let keys = Object.keys(obj)
    keys.forEach(key => {
        if (typeof obj[key] === 'object' && obj[key] !== null) {
            transformKeys(obj[key])
        }
        const newKey = key.replace(/_/i, '')
        obj[newKey] = obj[key]
        delete obj[key]
    })
}

方法四:广度优先遍历(非递归)

function bfs(obj) {
    const list = []
    if (!obj) return list
    const stack = []
    stack.push(obj)
    while (stack.length) {
        let item = stack.shift() // 和深度优先遍历的唯一差别
        for (let key in item) {
            if (typeof item[key] === 'object' && item[key] !== null) {
                list.push(item[key])
                stack.push(item[key])
            }
        }
    }
    return list
}

function transformKeys(obj) {
    const list = bfs(obj)

    list.forEach(item => {
        for (let key in item) {
            const newKey = key.replace(/_/i, '')
            item[newKey] = item[key]
            delete item[key]
        }
    })
}

transformKeys(a)
function stack(obj) {
    let arr = [obj];
    while ((ele = arr.pop())) {
        for (const key in ele) {
            if (Object.hasOwnProperty.call(ele, key)) {
                let o = ele[key];
                delete ele[key];
                let k = key.replace(/_?/g, "");
                ele[k] = o;
                typeof o === "object" && arr.push(o);
            }
        }
    }
    return obj;
}

commented
function fn(obj) {
  try {
    return JSON.parse(JSON.stringify(obj).replace(/(\"\w)_(\w\"\:)/g, '$1$2'))
  } catch (error) {
    console.error(error)
  }
}
const a = {
  a_y: {
    a_z: {
      y_x: 6
    },
    b_c: 1
  },
  n_u: 4
}

const replaceName = (obj) => {
  let stack = getKeyList(obj)

  while(stack.length) {
    let current = stack.shift()
    let child = current.parent[current.key]
    
    // 有下一层放进数组
    if(typeof child === 'object') {
      stack = stack.concat(getKeyList(child))
    }
    
    // 处理当前节点替换
    let newKey = current.key.replace('_', '')
    current.parent[newKey] = child
    delete current.parent[current.key]
  }
  
  return obj
}

const getKeyList = (obj) => {
  return Object.keys(obj).map(val => {
    return {
      key: val,
      parent: obj
    }
  })
}

console.log(replaceName(a))
function bfs(data) {
  let q = Object.keys(data).map(key => ({
    key,
    value: data[key],
    parent: data
  }))
  while (q.length) {
    let curr = q.shift()
    let keys = Object.keys(curr.value)
    let newKey = curr.key.replace(/_(\w)/g, function(_, $1) {
      return $1.toUpperCase()
    })
    curr.parent[newKey] = curr.value
    delete curr.parent[curr.key]
    if (keys.length) {
      q.push(...keys.map(key => ({
        key,
        value: curr.value[key],
        parent: curr.parent[newKey]
      })))
    }
  }
  return data
}
function changeKey(data){
   return  JSON.parse(JSON.stringify(data).replace(/_/g,''));
}
const a = {
    a_y: {
      a_z: {
        y_x: 6
      },
      b_c: 1
    }
  }
changeKey(a)

const a = {
a_y: {
a_z: {
y_x: 6
},
b_c: 1
}
}
const reg = /(\w+)(\w+)/g;
console.log(JSON.parse(JSON.stringify(a).replace(reg, (match) => match.replace('
', ''))))

const obj: any = {
  a_y: {
    a_z: {
      y_x: 6
    },
    b_c: 1
  }
}

const bfs = (root) => {
  const arr = [root];
  while(arr.length) {
    const current = arr.shift();
    for (let key of Object.keys(current)) {
      const changedKey = key.replace('_', '')
      current[changedKey] = current[key]
      delete current[key]
      arr.push(current[changedKey])
    }
  }
  console.log('result: ', root)
}

bfs(obj)

结果:
image

const a = {
    a_y: {
        a_z: {
            y_x: 6
        },
        b_c: 1
    }
}

function bgfObj(obj, fn) {
    let toString = Object.prototype.toString
    let queue = [obj]
    while (queue.length !== 0) {
        let temp = queue.shift()
        if ('Object]' === toString.call(temp).substring(8)) {
            queue.push(...Object.values(temp))
        }
        fn(temp)
    }
}
bgfObj(a, obj => {
    Object.keys(obj).forEach(key => {
        if (/_/.test(key)) {
            obj[key.replace('_', '')] = obj[key]  // 不考虑有多个 _
            delete obj[key]
        }
    })
})
console.log('bgfObj, a: ', JSON.stringify(a));

仿yancongwen方法二写的

const a = {
  a_y: {
    a_z: {
      y_x: 6,
    },
    b_c: 1,
  },
};

function formatKey(list) {
  const stack = [];
  stack.push(list);
  while (stack.length) {
    let item = stack.pop();
    for (let i in item) {
      if (typeof item[i] == "object" && item[i] != null) {
        stack.push(item[i]);
      }
      let newKey = i.replace(/_/i, "");
      item[newKey] = item[i];
      delete item[i];
    }
  }
  return list;
}
console.log(formatKey(a));

image

const getNewObj = (obj)=>{
  if(typeof obj !== 'object'){
    return obj
  }
  let keys = Object.keys(obj)
  keys?.length && keys.forEach(item=>{
    let newkey = ''
    if(/_/.test(item)){
      newkey = item.replace(/[_]/g,'')
    } else {
      newkey = item
    }
    obj[newkey] = getNewObj(obj[item])
    delete obj[item]
  })
  return obj
}
console.log(getNewObj(a))
const fn = obj => {
    let arr = [obj]
    while(arr.length) {
        const current = arr.shift()
        for (let key in current) {
            if (current.hasOwnProperty(key)) {
                const currentKey = key.replace('_', '')
                current[currentKey] = current[key]
                delete current[key]
                arr.push(current[currentKey])
            }
        }
    }
    return obj
}
console.log(fn(a))
// 迭代
const changeKey = (obj) => {
  const stack = [obj];
  while (stack.length) {
    const cur = stack.pop();
    for (let key in cur) {
      const newKey = key.replace("_", "");
      cur[newKey] = cur[key];
      delete cur[key];
      if (typeof cur[newKey] === "object") {
        stack.push(cur[newKey]);
      }
    }
  }
};

查看题目

// 非递归方法
function cloneAndFormat(obj) {
    var newObj = {};
    var arr = [
        {
            root: newObj,
            data: obj,
            key: "",
        },
    ];
    while (arr.length) {
        // 删除数组最后一项,返回删除的结果
        var cur = arr.pop();
        // 本次需要遍历的对象
        var data = cur.data;
        // 本次遍历的对象所属Key值,重新建立一个新的key来存放遍历对象的结果
        var curKey = cur.key;
        // 存储之前转换的结果
        var curRoot = cur.root;
        // 存储本次转换的结果
        var res = curRoot;
        // 为对应的Key值建立空对象Value
        if (curKey) {
            res = curRoot[curKey] = {};
        }
        for (var key in data) {
            var newKey = key.replace(/_/g, "");
            if (Object.prototype.toString.call(data[key]) === "[object Object]") {
                arr.push({
                    root: res,
                    data: data[key],
                    key: newKey,
                });
            } else {
                res[newKey] = data[key];
            }
        }
    }
    console.log(newObj)
    return newObj
}

cloneAndFormat(a)

// 输出 => 符合预期
// { ay: { bc: 1, az: { yx: 6, zd: 2 } } }

// 递归方法
function deepClone(obj) {
    var target = {};
    for (var key in obj) {
        var newKey = key.replace(/_/g, "");
        if (Object.prototype.toString.call(obj[key]) === "[object Object]") {
            target[newKey] = deepClone(obj[key]);
        } else {
            target[newKey] = obj[key];
        }
    }
    return target;
}
deepClone(a)
// 输出 => 符合预期
// { ay: { bc: 1, az: { yx: 6, zd: 2 } } }
// 有一个嵌套层次很深的对象,key 都是 a_b 形式 ,需要改成 ab 的形式,注意不能用递归。
const a = {
  a_y: {
    a_z: {
      y_x: 6,
    },
    b_c: 1
  },
};

// dfs 递归
function formatKeyDFS(item) {
  if (!item) return;
  for (let key in item) {
    console.log("key: ", key);
    if (typeof item[key] === "object" && item[key] !== null) {
      formatKeyDFS(item[key]);
    }
    let newKey = key.replace(/_/, "");
    item[newKey] = item[key];
    delete item[key];
  }
  return item;
}

// dfs 非递归
function formatKeyDFS2(obj) {
  let stack = [obj];
  while (stack.length) {
    let item = stack.pop();
    // 倒序遍历子节点
    let keys = Object.keys(item).reverse();
    for (let key of keys) {
      if (typeof item[key] === "object" && item[key] !== null) {
        stack.push(item[key]);
      }
      let newKey = key.replace(/_/, "");
      item[newKey] = item[key];
      delete item[key];
    }
  }
  return obj;
}

// bfs
function formatKeyBFS(obj) {
  let queue = [obj];
  while (queue.length) {
    let item = queue.shift();
    for (let key in item) {
      console.log("key: ", key);
      if (typeof item[key] === "object" && item[key] !== null) {
        queue.push(item[key]);
      }

      let newKey = key.replace(/_/, "");
      item[newKey] = item[key];
      delete item[key];
    }
  }
  return obj;
}

console.log(formatKeyDFS2(a));

{ ay: { bc: 1, az: { yx: 6 } } }
function chanKey(arr) {
    let sk = [arr]//遇到对象就进栈
    let sk1 = []//缓存执行对象结果
    //当栈内元素为空时结束
    while(sk.length){
        let last = sk.pop()//弹出栈顶一项
        Object.keys(last).forEach(el=>{
            let key = el.replace('_','')
            last[key] = last[el]
            delete last[el]
            sk1.push(last)
            if(typeof last[key] == 'object' ){
                sk.push(last[key])
            }
        })
    }
    return sk1[0]
}
console.log(chanKey(a));

let o = {
a_y: {
a_z: {
y_x: 6,
},
b_c: 1,
},
}

function formatObject(raw){
const q = []
q.push(raw)
for(const i of q) {
if(typeof i === 'object' && Object.keys(i).length > 0) {
for(const key of Object.keys(i)){
const newKey = key.replace('_', '')
i[newKey] = i[key]
q.push(i[newKey])
if (newKey !== key) {
delete i[key]
}
}
}
}
return raw
}
formatObject(o)

commented

`

const transfer = param => {
return param.split('_').join('')
}

const chageKey = (pObj) => {
var obj = {};
for(var i in pObj) {
if(pObj.hasOwnProperty(i) && typeof pObj[i] === 'object') {
obj[${transfer(i)}] = run(pObj[i])
} else if(pObj.hasOwnProperty(i)) {
obj[${transfer(i)}] = pObj[i]
}
}
return obj
}

`

commented
function replaceName(obj) {
  let stack = [obj];

  while (stack.length) {
    let curObj = stack.pop();
    let keys = Object.keys(curObj);

    keys.forEach((key) => {
      let newKey = key.replace("_", "");
      curObj[newKey] = curObj[key];
      delete curObj[key];

      if (typeof curObj[newKey] === "object") {
        stack.push(curObj[newKey]);
      }
    });
  }
}
replaceName(a);
const a = {
  a_y: {
    a_z: {
      y_x: 6,
    },
    b_c: 1,
  },
};
// {
//   ay: {
//     az: {
//       yx: 6
//     },
//     bc: 1
//   }
// }

// 简单快捷,但是很不可靠的方法

function remove_(obj) {
  const string = JSON.stringify(obj).replace(/_/g,"")
  const json = JSON.parse(string)
  console.log(json);
  return string;
}

remove_(a)
const transformKey = (obj: {
    [key: string]: any
  }) => {
    const queue: {
      [key: string]: any
    }[] = [obj];

    while(queue.length) {
      const _current = queue.shift()!;
      Object.keys(_current).forEach((key) => {

        const _newKey = key.replace(/_/g, '');

        _current[_newKey] = _current[key];

        delete _current[key];

        if (typeof _current[_newKey] === 'object') {
          queue.push(_current[_newKey]);
        }
      })
    }

    return obj;
  }

前言

参考前面大佬的写法 实在是想不到 怎么不使用递归的方法实现


方法一

  • 实际上是 利用数组的特性进行递归
  • 遍历数组中的每个key 进行修改
const a = {
  a_y: {
    a_z: {
      y_x: 6
    },
    b_c: 1
  }
}

function bfs(target) {
    const list = [target];
    const reg = /\_/;
    while (list.length > 0) {
        const current = list.pop(); // 随意拿到一个当前的值
        for (let key of Object.keys(current)) {
            const afterKey = key.replace(reg, '');
            current[afterKey] = current[key];
            delete current[key]
            // 判断是否为对象
            if (Object.prototype.toString.call(current[afterKey]) === '[object Object]') {
                list.push(current[afterKey]); // 利用数组的特性递归 实际上也是递归的一种
            }
        }
    }
    console.log(target);
    return target
}

console.time()
bfs(a)
console.timeEnd()

思路:先将对象序列化,再按照题目要求修改 key,最后再将序列化后的字符串解析为对象

const a = {
  a_y: {
    a_z: {
      y_x: 6,
    },
    b_c: 1,
  },
}

function updateKey(obj) {
  return JSON.parse(JSON.stringify(obj).replace(/(\w)_(\w)/g, '$1$2'))
}

console.log(updateKey(a))

采用队列的方法处理树数据

  1. 左边节点出队
  2. 出队非叶节点,将子节点cancat进队列中
  3. 根据引用关系,改变出队节点父节点的key值,将出队节点children赋值给删除'_'的节点
  4. while循环至队列为空
function flatSingle(obj) {
  return Object.keys(obj).map(k => ({ parent: obj, key: k, value: obj[k] }))
}

function flatFunc(obj) {
    let queue = flatSingle(obj, obj)
    while (queue.length) {
      const left = queue.shift();
      const key = left.key.replace(/_/g, '');
      if (Object.prototype.toString.call(left.value) === '[object Object]') {
        queue = queue.concat(flatSingle(left.value))
      }
      left.parent[key] = left.value;
      if (left.key.includes('_')) {
        delete left.parent[left.key];
      }
    }
    return obj;
}
commented
const a = {
  a_y: {
    a_z: {
      y_x: 6
    },
    b_c: 1
  }
}
// {
//   ay: {
//     az: {
//       yx: 6
//     },
//     bc: 1
//   }
// }

function modifyKey(input) {
  const obj = JSON.stringify(input).replace(/_/g, '')
  return JSON.parse(obj)
}

console.log(modifyKey(a))
commented
const transfer = function (obj) {
  const arr = [obj];
  while (arr.length) {
    const item = arr.shift();
    for (let i in item) {
      if (Object.prototype.toString.call(item[i]) === "[object Object]") {
        arr.push(item[i]);
      }
      item[i.replace(/_/, "")] = item[i];
      delete item[i];
    }
  }
  return obj;
};
commented
const changeKey = (obj) => {
  let stack = [obj]
  while (stack.length) {
    let cur = stack.pop()
    for (let key in cur) {
      let newKey = key.replace('_', '')
      cur[newKey] = cur[key]
      delete cur[key]
      if (cur[newKey] instanceof Object) {
        stack.push(cur[newKey])
      }
    }
  }
};
commented

function adc(data) {
let arr = [data];
while (arr.length != 0) {
const target = arr.pop();
change(target); // 对对象里的数据进行名称转化
if (target instanceof Object) { // 如果是对象的话,继续将他的属性加进去
for (let i in target) {
arr.push(target[i]);
}
}
}
console.log(data);
return data;
};
const change = (data) => {
const key = Object.keys(data);
const reg = /_/g;
for (let i = 0; i < key.length; i++) {
let tempKey = key[i].replace(reg, '');
data[tempKey] = data[key[i]];
delete data[key[i]];
}
};
const a = {
a_y: {
a_z: {
y_x: 6,
z_j: 7,
},
b_c: 1
}
}
adc(a)

// 有一个嵌套层次很深的对象,key 都是 a_b 形式 ,需要改成 ab 的形式,注意不能用递归。

const a = {
  a_y: {
    a_z: {
      y_x: 6
    },
    b_c: 1
  }
}
// {
//   ay: {
//     az: {
//       yx: 6
//     },
//     bc: 1
//   }
// }

function changeObjectProperty(obj) {
    let reg = new RegExp(/("\w+)_(\w+":)/g);
    return JSON.parse(JSON.stringify(obj).replace(reg, '$1$2'))
}

console.log(changeObjectProperty(a));

function fn(obj) {
let stack = []
stack.push(obj)
while(stack.length) {
for (let i in stack[0]) {
let item = stack[0]
let name = i.replace(/_/,'')
item[name] = item[i]
delete item[i]
if (typeof item[name] === 'object' && item[name] !== null) {
stack.push(item[name])
}
}
stack.shift()
}
return obj
}

commented
function updateKey(obj) {
  if (Object.prototype.toString.call(obj) === '[object Object]') {
     return JSON.parse(JSON.stringify(obj).replace(/_/g, ''));
  }
  return obj;
}

使用递归
function updateObj(obj) {
if (obj !== null && typeof obj === 'object') {
Object.keys(obj).forEach((key) => {
const key1 = key.replace(/_/g, '')
obj[key1] = obj[key]
delete obj[key]
return updateObj(obj[key1])
})
}
return obj
}

// 非递归实现
let changeObjName = function(obj) {
    let stack = [obj];
    while(stack.length) {
        let top = stack.pop();
        for(let key in top) {
            if(Object.prototype.toString.call(top) === '[object Object]') {
                stack.push(top[key])
            }
            top[key.split('_').join('')] = top[key];
            delete top[key];
        }
    }
    return obj;
}

//递归实现
let changeObjName = function(obj) {   
    return Object.keys(obj).reduce((newObj, key)=> {
        let newKey = key.split('_').join('');
        newObj[newKey] = (obj && typeof obj[key] === 'object') ? changeObjName(obj[key]): obj[key];
        return newObj;
    }, {})  
}
const a = {
        a_y: {
            a_z: {
                y_x: 6
            },
            b_c: 1
        }
    }
    function dfs(obj = {}) {
        const stack = []
        const list = []
        stack.push(obj)
        list.push(obj)
        while (stack.length) {
            const item = stack.pop()
            for (const key in item) {
                if (typeof item[key] === 'object') {
                    stack.push(item[key])
                    list.push(item[key])
                }
            }
        }
        return list
    }

    function transferKey(obj) {
        const list = dfs(obj)
        list.forEach(item => {
            for (const key in item) {
                const newKey = key.replace(/_/g, '')
                item[newKey] = item[key]
                delete item[key]
            }
        })
    }
    transferKey(a)
    console.log(a)
 const getNewKey = (obj) => {
    try {
        const reg = /(\w+)_(\w+)":/g
        return JSON.parse(JSON.stringify(obj).replace(reg, (match) => match.replace('_', '')))
    } catch (error) {
        return obj
    }
}
//这周六会重新再写一遍, 目前对 深度优先遍历和广度优先变量不熟
const transformObj= (obj) => {
let res = Object.keys(obj)  ;
  while (res.length) {
    let cur = res.pop()
    for (let key in cur) {
      let newKey = key.replace('_', '')
      cur[newKey] = cur[key]
      delete cur[key]
      if (cur[newKey] instanceof Object) {
        res.push(cur[newKey])
      }
    }
  }
};
const fn = obj => {
  let queue = [obj];
  while(queue.length) {
    let res = queue.pop();
    for(let key in res) {
      if(typeof res[key] === 'object' && res[key] !== null) {
        queue.push(res[key]);
      }

      let newKey = key.replace(/_/, '');
      res[newKey] = res[key];
      delete res[key]
    }
  }
  return obj
};
学习了大佬的bfs
function changeKey(obj) {
  let stack = [];
  let resList = [];
  stack.push({ obj });
  while (stack.length !== 0) {
    let cur = stack.pop();
    Object.keys(cur).forEach((key) => {
      if (typeof cur[key] === "object" && !Array.isArray(cur[key])) {
        resList.push(cur[key]);
        stack.push(cur[key]);
      }
    });
  }
  resList.forEach((item) => {
    Object.keys(item).forEach((key) => {
      let newKey = key.replace(/_/g, "");
      item[newKey] = item[key];
      delete item[key];
    });
  });
}
function modifyKey(obj){
    for(const key in obj){
        let k1 = key.replaceAll("_","");
        if(!(obj[key] instanceof Object)){
            obj[k1] = obj[key]
        }else{
            obj[k1] = modifyKey(obj[key]);
        }
        delete obj[key]
    }
    return obj;
}
function modifyKey(obj){
            if(!(obj instanceof Object)){
                return obj;
            }
            let d = {};
            for(const key in obj){
                let k1 = key.replaceAll("_","");
                d[k1] = modifyKey(obj[key]);
            }
            return d;
        }
const changeKey = (obj, newObj) => { 
    const keys=Object.keys(obj);
    for(let i = 0; i < keys.length; i++) {
        const key = keys[i];
        newObj[key.replace('_', '')] = obj[key];
        if(typeof obj[key] === 'object') {
            newObj[key.replace('_', '')] ={};
            changeKey(obj[key], newObj[key.replace('_', '')]);
        } 
       
    }
    return newObj;
}
const a = {
    a_y: {
      a_z: {
        y_x: 6
      },
      b_c: 1
    }
  }
changeKey(a, {})

image

function handler(obj) {
  function isObject(target) {
    if (Array.isArray(target)) return false;
    return target !== null && typeof target === "object";
  }
  function dfs(obj) {
    if (!isObject(obj)) return;
    Object.keys(obj).forEach((key) => {
      const newKey = key.replaceAll("_", "");
      obj[newKey] = obj[key];
      delete obj[key];
      dfs(obj[newKey]);
    });
  }
  dfs(obj);
  return obj;
}
commented
function transformKey(object) {
  const array = [object]
  while (array.length) {
    const obj = array.pop()
    for (let key in obj) {
      if (Object.prototype.toString.call(obj[key]) === "[object, Object]") {
        array.push(obj[key])
      }
      obj[key.replace(/_/, "")] = obj[key]
      delete obj[key]
    }
  }
  return object
}
// 正则要考虑到属性值是不是包含_
const a = {
  a_y: {
    a_z: {
      y_x: 6
    },
    b_c: 'asdas_c'
  }
}

function resolve (obj) {
  let objStr = JSON.stringify(obj)
  let arr = objStr.match(/"\w_\w":/g).map(item => item.replace(/_/g,''))
  for(let i of arr){
    objStr = objStr.replace(/"\w_\w":/, i)
  }
  return JSON.parse(objStr)
}

console.log(resolve(a))
const keyTransformer = (obj, fn) =>
    Object.keys(obj).reduce((acc, current) => {
        const key = fn(current);
        const val = obj[current];
        acc[key] =
          val !== null && typeof val === 'object' ? keyTransformer(val, fn) : val;
        return acc;
      }, {});

const a = {
  a_y: {
    a_z: {
      y_x: 6
    },
    b_c: 'asdas_c'
  }
};
const underscoreKeysObj = keyTransformer(a, key => key.split('_').join(''));
// bfs 广度优先遍历
function removeUnderScore(a) {
    const queue = [a];
    const obj = {};

    while(queue.length) {
        const item = queue.pop();

        for (let key in item) {
            const newKey = key.replace('_', '');
            item[newKey] = item[key];
            delete item[key];

            // 如果是对象,推入队列继续
            if (typeof item[newKey] === 'object' && item[newKey] !== null) {
                queue.unshift(item[newKey]);
            }
        }
    }

    return a;
}

const a = removeUnderScore({
    a_y: {
      a_z: {
        y_x: 6
      },
      b_c: 1
    }
});

console.log(a);
function transfer(obj) {
  return JSON.parse(JSON.stringify(obj).replace(/"(\w)_(\w):"/g, '$1$2:'));
}

想了好长时间用了一个笨办法

const editDeepKey = (obj = {}) => {
    const result = {}; // 处理的结果
    const shed = []; // 栈信息
    let index = 0; // 当前栈索引

    // 推进第一级入栈
    Object.keys(obj).length && shed.push({
        obj: obj,
        keys: Object.keys(obj), // 第一级所有的key
        convert_key: '', // 转化之后的key
        index: 0, // 遍历索引
    });

    while (shed.length) {
        const current = shed[index];  // 当前内容栈
        let receive_data = result; // 接收对象
        const key = current.keys[current.index]; // 当前遍历原数据的key
        let convert_key = ''; // 转化之后的key值

        // 如果key不存在说明是上次上级遇到对象进行子级处理,回到上级之后之前是对象的key处于最后一个位置,后面无需在进行处理
        // 直接将该栈数据删除出栈即可
        if (!key) {
            shed.splice(index, 1); // 清空当前栈内存
            index--; // 减少栈索引

            // 继续下一轮循环
            continue;
        }

        convert_key = key.replace(/([a-zA-Z])_([a-zA-Z])/g, '$1$2'); // 当前遍历目标数据的key
        shed[index].convert_key = convert_key; // 赋值当前遍历目标数据的key

        // for循环确定最终的接收对象
        for (let i = 0; i < index; i++) {
            // 这里不用担心receive_data[shed[i].convert_key]不存在
            // 因为在上次检测到父级key对应的值是一个对象的时候就创建对应的对象

            // 直接等于该对象
            receive_data = receive_data[shed[i].convert_key];
        }

        if (Object.prototype.toString.call(current.obj[key]) === '[object Object]') {
            // 将当前键的值赋值为一个空对象 这里创建相关对象,涉及到上面for循环里面的直接赋值
            receive_data[convert_key] = {}; // 先创建对应键为对象

            // 压栈
            shed.push({
                obj: current.obj[key],
                keys: Object.keys(current.obj[key]), // 当前级所有的key
                convert_key: '', // 转化之后的key
                index: 0, // 遍历索引
            });

            // 增加栈索引
            index++;
            // 索引加1
            current.index++;

            // 继续下一轮循环
            continue;
        }

        // 非对象值
        // 索引加1
        current.index++;
        receive_data[convert_key] = current.obj[key]; // 赋值

        // 本次栈内容全部处理完成 出栈
        if (current.index === current.keys.length) {
            shed.splice(index, 1); // 清空当前栈内存
            index--; // 减少栈索引
        }
    }

    return result;
};

const a = {
    a_y: {
        a_z: {
            y_x: 6
        },
        b_c: 1
    }
};
console.time('time');
console.log(editDeepKey(a));
console.timeEnd('time');