第九题:修改嵌套层级很深对象的 key
KieSun opened this issue · comments
有一个嵌套层次很深的对象,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('耗时');
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;
}
};;
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;
}
栈
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)
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));
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)
`
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
}
`
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))
采用队列的方法处理树数据
- 左边节点出队
- 出队非叶节点,将子节点cancat进队列中
- 根据引用关系,改变出队节点父节点的key值,将出队节点children赋值给删除'_'的节点
- 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;
}
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))
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;
};
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])
}
}
}
};
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
}
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, {})
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;
}
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');