第 111 题:编程题,写个程序把 entry 转换成如下对象
yygmind opened this issue · comments
var entry = {
a: {
b: {
c: {
dd: 'abcdd'
}
},
d: {
xx: 'adxx'
},
e: 'ae'
}
}
// 要求转换成如下对象
var output = {
'a.b.c.dd': 'abcdd',
'a.d.xx': 'adxx',
'a.e': 'ae'
}
我先来
function flatObj(obj, parentKey = "", result = {}) {
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
let keyName = `${parentKey}${key}`;
if (typeof obj[key] === 'object')
flatObj(obj[key], keyName+".", result)
else
result[keyName] = obj[key];
}
}
return result;
}
function isObject (obj) {
return Object.prototype.toString.call(obj) === '[object Object]'
}
function flatObj (obj, prefix = '', res = {}) {
for (let i in obj) {
let key = prefix ? prefix + '.' + i : i
isObject(obj[i]) ? flatObj(obj[i], key, res) : (res[key] = obj[i])
}
return res
}
var entry = {
a: {
b: {
c: {
dd: 'abcdd'
}
},
d: {
xx: 'adxx'
},
e: 'ae'
}
}
var keys = [];
function flatObj(from, to) {
for (var key in from) {
var res = from[key];
keys.push(key);
if (typeof res === "object") {
flatObj(res, to);
} else {
to[keys.join(".")] = res;
}
keys.pop();
}
}
var output = {};
flatObj(entry, output);
console.log(output);
function en(obj) {
const keyArr = [];
const newObj = {};
const _c = function (o) {
for (k in o) {
keyArr.push(k);
if (typeof o[k] === 'object') {
_c(o[k]);
} else {
newObj[keyArr.join('.')] = o[k];
keyArr.pop();
}
}
keyArr.pop();
}
_c(obj);
return newObj;
}
bfs
function flatObj(entry) {
const queue = Object.entries(entry)
const res = {}
while (queue.length) {
const [key, obj] = queue.pop()
for (const [k, v] of Object.entries(obj)) {
if (typeof v !== 'object') {
res[`${key}.${k}`] = v
} else {
queue.push([`${key}.${k}`, v])
}
}
}
return res
}
function func (origin, output = {}, keys = []) => {
if (typeof origin === 'object') {
for (const k in origin) {
generate(origin[k], output, [...keys, k])
}
} else {
output[keys.join('.')] = origin
}
}
const output = {}
func(entry, output)
console.log('output', output)
var obj = {
a: {
b: {
c: {
dd: 'abcdd'
}
},
d: {
xx: 'adxx'
},
e: 'ae'
}
};
function convert(target,preKey = '',result = {}){
let keys = Object.keys(target),
len = keys.length;
while(len--){
let curKey = keys[len];
let targetKey = preKey ? `${preKey}.${curKey}` : curKey;
if(Object.prototype.toString.call(target[curKey]) === '[object Object]'){
convert(target[curKey],targetKey,result);
}else{
result[targetKey] = target[curKey];
}
}
return result;
}
console.log(convert(obj));
function flat(obj, key = "", res = {}) {
Object.keys(obj).forEach(k => {
if (Object.prototype.toString.call(obj[k]) == "[object Object]") {
flat(obj[k], key + k + ".", res);
} else {
res[key + k] = obj[k];
}
});
return res;
}
console.log(flat(entry));
题目
var entry = {
a: {
b: {
c: {
dd: 'abcdd'
}
},
d: {
xx: 'adxx'
},
e: 'ae'
}
};
// 要求转换成如下对象
var output = {
'a.b.c.dd': 'abcdd',
'a.d.xx': 'adxx',
'a.e': 'ae'
};
实现方案
思路 遍历对象,遇到还是对象的地方递归深入即可。
核心代码:
/**
*
* @param {String | null} prevKey 前面的key
* @param {Object} obj 当前操作对象
* @returns {Array<Object>} 扁平化后的对象数组
*/
function getFlat(prevKey, obj) {
const arr = [];
Object.keys(obj).forEach(k => {
const currentKey = prevKey ? `${prevKey}.${k}` : k;
if (Object.prototype.toString.call(obj[k]) != '[object Object]') {
arr.push({
[currentKey]: obj[k]
});
} else {
arr.push(...getFlat(currentKey, obj[k]));
}
});
return arr;
}
以给定代码为例,即可转化为如下形式,然后进行合并即可。
[
{'a.b.c.dd': 'abcdd'},
{'a.d.xx': 'adxx'},
{'a.e': 'ae'},
]
如果不考虑纯函数的问题,可以初始就定义一个空对象,然后在递归函数中直接将每次的结果写入,这样就少了后续的合并操作,详见后续实现中的 flatObject2
。
完整代码
var entry = {
a: {
b: {
c: {
dd: 'abcdd'
}
},
d: {
xx: 'adxx'
},
e: 'ae'
}
};
/**
* 对象扁平化
* @param {Object} obj 操作对象
* @returns {Object} 扁平化后的对象
*/
function flatObject(obj) {
const flat = {};
return Object.assign(flat, ...getFlat(null, obj));
/**
*
* @param {String | null} prevKey 前面的key
* @param {Object} obj 当前操作对象
* @returns {Array<Object>} 扁平化后的对象数组
*/
function getFlat(prevKey, obj) {
const arr = [];
Object.keys(obj).forEach(k => {
const currentKey = prevKey ? `${prevKey}.${k}` : k;
if (Object.prototype.toString.call(obj[k]) != '[object Object]') {
arr.push({
[currentKey]: obj[k]
});
} else {
arr.push(...getFlat(currentKey, obj[k]));
}
});
return arr;
}
}
console.log(JSON.stringify(flatObject(entry), 0, 4));
// {
// "a.b.c.dd": "abcdd",
// "a.d.xx": "adxx",
// "a.e": "ae"
// }
/**
* 对象扁平化
* @param {Object} obj 操作对象
* @returns {Object} 扁平化后的对象
*/
function flatObject2(obj) {
const flat = {};
getFlat(null, obj);
return flat;
/**
* 递归将对象扁平化
* @param {String | null} prevKey 前面的key
* @param {Object} obj 当前操作对象
*/
function getFlat(prevKey, obj) {
Object.keys(obj).forEach(k => {
const currentKey = prevKey ? `${prevKey}.${k}` : k;
if (Object.prototype.toString.call(obj[k]) != '[object Object]') {
flat[currentKey] = obj[k];
} else {
getFlat(currentKey, obj[k]);
}
});
}
}
console.log(JSON.stringify(flatObject2(entry), 0, 4));
// {
// "a.b.c.dd": "abcdd",
// "a.d.xx": "adxx",
// "a.e": "ae"
// }
function flatObj(entry){
function rec (entry, parentKey , result){
Object.keys(entry).forEach((key) => {
if(typeof entry[key] === 'object') {
rec(entry[key], parentKey + key, result)
} else {
const keyname = parentKey.replace(/(?=\B)/g, '.')+ '.' +key
result[keyname] = entry[key]
}
})
}
rec(entry, parentKey = '', result = {})
return result
}
function flatObj(obj) {
let arr = Object.entries(obj);
arr.map(item => {
if(typeof item[1] === 'object'){
let keys = Object.keys(item[1]);
let values = Object.values(item[1]);
let temp = {};
for(let i=0;i<keys.length;i++) {
temp[${item[0]}.${keys[i]}
] = values[i]
}
flatObj(temp)
}else {
output[item[0]] = item[1];
}
})
}
function objs(_old,key,_new){
if(!key) key = '';
if(!_new)_new = {};
for(let attr in _old){
let data = _old[attr];
if(data!=null && typeof data === 'object'){
objs(data,key+attr+'.',_new);
}else{
_new[key+attr] = data;
}
}
return _new;
}
console.log(objs({
a:{
b:{
c:{
dd:'abcdd'
}
},
d:{
xx:{
cc:'xxxx'
}
},
e:'ae',
g:{
ooxx:'xxx'
}
}
}));
function flatJson(obj = {}, parentKey = '', res = {}) {
for (let k in obj) {
if (typeof obj[k] !== 'object' && obj[k] !== null) {
res[`${parentKey}${k}`] = obj[k];
} else {
flatJson(obj[k], `${parentKey}${k}.`, res);
}
}
return res;
}
大相径庭
var entry = {
a: {
b: {
c: {
dd: 'abcdd'
}
},
d: {
xx: 'adxx'
},
e: 'ae'
}
}
/**
* [getFlat]
* @param {[Object]} entry [传入对象]
* @param {String} hea [属性名前缀]
* @param {Object} res [返回对象]
*/
function getFlat (entry, hea = '', res = {}) {
for (let k in entry) {
if (entry.hasOwnProperty(k)) {
if (Object.prototype.toString.call(entry[k]) === '[object Object]' ) {
getFlat(entry[k], hea + k + '.', res)
} else {
res[hea + k] = entry[k]
}
}
}
return res
}
console.log(getFlat(entry))
// 1.先遍历,判断是否包含属性
// 2.属性值是对象继续递归
// 3.属性值不是对象返回
const flattenObject = (obj, prefix = '') =>
Object.keys(obj).reduce((acc, k) => {
const pre = prefix.length ? prefix + '.' : '';
if (typeof obj[k] === 'object') Object.assign(acc, flattenObject(obj[k], pre + k));
else acc[pre + k] = obj[k];
return acc;
}, {})
function chang(obj, parentKey = '', res = {}) {
for(let i in obj) {
let Key = parentKey ? (parentKey + '.' + i) : i;
(typeof obj[i] === 'object')?chang(obj[i], Key, res):res[Key] = obj[i];
}
return res
}
console.log(chang(entry))//{a.b.c.dd: "abcdd", a.d.xx: "adxx", a.e: "ae"}
function fun111(entry) {
let array111 = {}
function fun111_1 (entry, f) {
for (let i in entry) {
let t = f ? ${f}.${i}
: i
if (typeof entry[i] === 'string') {
array111[t] = entry[i]
} else {
fun111_1(entry[i], t)
}
}
}
fun111_1(entry)
return array111
}
`var entry = {
a: {
b: {
c: {
dd: 'abcdd'
}
},
d: {
xx: 'adxx'
},
e: 'ae'
}
}
function getOutput(obj){
let parentKey = '';
let output = {};
if(Object.prototype.toString.call(entry) === '[object Object]'){
(function getKeys(obj, str){
for(let key in obj){
let newStr = str === '' ? key : `${str}.${key}`;
if(Object.prototype.toString.call(obj[key]) === '[object Object]'){
getKeys(obj[key], newStr);
}else{
output[newStr] = obj[key];
}
}
})(obj, '')
}else{
console.log('传入的不是对象');
}
return output;
}
getOutput(entry)`
var entry = {
a: {
b: {
c: {
dd: 'abcdd'
}
},
d: {
xx: 'adxx'
},
e: 'ae'
}
}
const deepFlat = (obj) => {
let res = {}
function deep(obj, prekey = '') {
for (let key of Object.keys(obj)) {
if (typeof obj[key] === 'object' && !Array.isArray(obj[key])) {
deep(obj[key], prekey ? `${prekey}.${key}` : key)
} else {
res[`${prekey}.${key}`] = obj[key]
}
}
}
deep(obj)
return res
}
console.log(deepFlat(entry))
function fun1(obj, str = '', result = {}) {
Object.keys(obj).forEach((key) => {
if (typeof obj[key] == 'object') {
fun1(obj[key], str + key + '.', result)
} else {
str += key
result[str] = obj[key]
}
})
return result
}
console.log(fun1(entry))
上一版typescript实现
function transformObject(input: any, keyStr: string='', result: any={}): any{
const keys: Array<string> = Object.keys(input);
keys.map(key => {
if (typeof input[key] === 'object') {
transformObject(input[key], keyStr+`${key}.`, result)
} else {
keyStr += `${key}`;
result[keyStr] = input[key];
}
})
return result
}
const isObject = (value) => (typeof value === 'object') && (value !== null)
function reduceObject(obj, parentName, resultObj) { // 对 {} 的每个值进行判断
const keyNames = Object.keys(obj); // ['b', 'd']
keyNames.forEach(keyName => {
let currentValue = obj[keyName] // 当前值
let currentKeyName = parentName ? `${parentName}.${keyName}` : keyName // 当前键名
// 键值为对象则继续递归, 为其它值则将新的键值对添加到result中
if(isObject(currentValue)) {
reduceObject(currentValue, currentKeyName, resultObj)
} else {
resultObj[currentKeyName] = currentValue
}
})
}
function flatKeyName(obj) {
let outputObj = {}
reduceObject(entry, null, outputObj)
return outputObj
}
console.log(flatKeyName(entry))
function isPlainObject(obj){
return Object.prototype.toString.call(obj) === '[object Object]'
}
const output = {}
function parserObj(obj,parentKey=''){
if(isPlainObject(obj)){
Object.keys(obj).forEach(key=>{
parserObj(obj[key],`${parentKey}${key}.`)
})
}else{
output[parentKey] = obj
}
}
var entry = {
a: {
b: {
c: {
dd: 'abcdd'
}
},
d: {
xx: 'adxx'
},
e: 'ae'
}
}
parserObj(entry)
console.log(output)
function flatObj(preKey, obj, result = {}) {
if (JSON.stringify(obj) === '{}') {
return {};
}
for (var key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
const curKey = preKey ? `${preKey}.${key}` : key;
if (typeof obj[key] !== 'object') {
result[curKey] = obj[key];
} else {
flatObj(curKey, obj[key], result);
}
}
}
return result;
}
function flatObj(entry, prev = "", result = {}) {
Object.keys(entry).map((key) =>
typeof entry[key] === "object"
? flatObj(entry[key], prev ? key : `${prev}.${key}`, result)
: (result[prev ? key : `${prev}.${key}`] = entry[key])
);
return result;
}
a: {
b: {
c: {
dd: 'abcdd'
}
},
d: {
xx: 'adxx'
},
e: 'ae'
}
}
function exchange(obj) {
if (typeof obj != 'object') {
throw new Error('请输入 [object Object] 类型')
}
let O = {}
let digui = function(obj, str) {
for (let key in obj) {
let str_ = str + '.' + key
if (typeof obj[key] == 'object') {
digui(obj[key], str_)
} else {
O[str_.slice(1)] = obj[key]
}
}
}
let res = digui(obj, '')
return O
}
let res = exchange(entry)
console.log(res) //{a.b.c.dd: "abcdd", a.d.xx: "adxx", a.e: "ae"}
var entry = {
a: {
b: {
c: {
dd: 'abcdd',
},
},
d: {
xx: 'adxx',
},
e: 'ae',
},
}
function flatPlainObj(entry) {
if (Object.prototype.toString.call(entry) !== '[object Object]') {
throw new Error('entry must be a plain object')
}
var output = {}
var pathArr = []
function recur(entry) {
if (Object.prototype.toString.call(entry) === '[object Object]') {
Object.keys(entry).forEach(key => {
pathArr.push(key)
recur(entry[key])
pathArr.pop()
})
} else {
output[pathArr.join('.')] = entry
}
}
recur(entry)
return output
}
console.log(flatPlainObj(entry))
function flattern(o, path = '', res = {}) {
Object.keys(o).forEach((key) => {
if (Object.prototype.toString.call(o[key]) === '[object Object]' || Array.isArray(o[key])) {
flattern(o[key], `${path}.${key}`, res)
} else {
res[`${path}.${key}`.slice(1)] = o[key]
}
});
return res
}
深度遍历
function convert(entry) {
const queue = [];
const output = {};
function dft(obj) {
const keys = Object.keys(obj);
for (let i of keys) {
queue.push(i);
if (typeof obj[i] === 'object') {
dft(obj[i]);
} else {
output[queue.join('.')] = obj[i];
}
queue.pop();
}
}
dft(entry);
return output;
}
function f1() {
var str = '',obj = {};
return function (en) {
for(var i in en){
if(Object.prototype.toString.call(en[i])=="[object Object]" ){
str+=i+'.';
arguments.callee(en[i],str);
str = str.slice(0,str.length-1-i.length);
}else{
str+=i;
obj[str] = en[i];
str = str.slice(0,str.length-1-i.length)+'.';
}
}
console.log(obj);
}
}
var cc =f1()(entry);
不用闭包是不完美的!
var arr = []
output = (entry, key = '') => {
for (var [k, v] of Object.entries(entry)) {
if (Object.prototype.toString.call(v) === '[object Object]') {
this.output(v, key + k + '.')
} else {
arr.push([key + k, v])
}
}
}
output(entry)
Object.fromEntries(arr)
这个编辑器也太难用了吧~~~~~
function flatObj(obj, keyList = [], retObj = {}) {
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
let newkeyList = [...keyList]
newkeyList.push(key)
if (typeof obj[key] === 'object') {
flatObj(obj[key], newkeyList, retObj);
} else {
var str = newkeyList.join('.')
retObj[str] = obj[key]
}
}
}
return retObj;
}
function selfFlat (obj, keystr="", newObj = {}) {
for (key in obj) {
if (!obj.hasOwnProperty(key)) continue; // 判断是否存在该属性
let newkeystr = keystr ? keystr + '.' + key : key;
if(obj[key] instanceof Object) {
selfFlat(obj[key], newkeystr, newObj) // 如果当前还是个对象递归
}
else {
newObj[newkeystr] = obj[key] // 否之将键值对赋予新对象
}
}
return newObj;
}
深度优先遍历
function transform(v, k, output = {}) {
Object.keys(v).forEach(key => {
if (typeof v[key] === 'object') {
return transform(v[key], k ? `${k}.${key}` : key, output)
}
output[`${k}` ? `${k}.${key}` : key] = v[key]
})
return output
}
let target = {
a: {
b: {
c: 1
}
},
b: {
c: 2
},
d: {
a: {
b: {
c: {
e: 3
}
}
}
}
}
let getRes = (function formatObj (target) {
let objRes = {}
let init = function (obj = {}, name = '') {
let propArr = Object.keys(obj)
if (propArr.length) {
propArr.forEach(item => {
init(obj[item], name ? `${name}.${item}` : `${item}`)
})
} else {
objRes[name] = obj
}
return objRes
}
return init
})(target)
let res = getRes(target)
顺便问一句,为啥大佬们出来的代码是彩色的,是我操作姿势不对么。。囧RZ
function flatObjTO(obj,parentKey = "",result={}){
for (var key in obj){
debugger;
let keyName = `${parentKey}${key}`;
if (typeof obj[key]=== 'object'){
flatObjTO( obj[key] ,keyName+"." ,result);
} else {
result[keyName]=obj[key];
}
}
return result;
}
var entry = {
a: {
b: {
c: {
dd: 'abcdd'
}
},
d: {
xx: 'adxx'
},
e: 'ae'
}
};
console.log(flatObjTO(entry));
学习了
function flatten(entry, p, result = {}) {
var keys = Object.keys(entry);
return keys.reduce((acc, key) => {
let newp = key;
if (p) { newp = p + '.' + newp }
if (typeof entry[key] === 'string') {
acc[newp] = entry[key]
return acc
} else {
return a(entry[key], newp, result)
}
}, result)
}
function flatten(entry, p, result = {}) { var keys = Object.keys(entry); return keys.reduce((acc, key) => { let newp = key; if (p) { newp = p + '.' + newp } if (typeof entry[key] === 'string') { acc[newp] = entry[key] return acc } else { return a(entry[key], newp, result) } }, result) }
代码是怎么变色的?
var entry = {
a: {
b: {
o: 'o',
c: {
dd: 'abcdd'
}
},
d: {
xx: 'adxx'
},
e: 'ae'
}
}
let totalKey = ''
let result = {}
function convertObj(obj,totalKey){
Object.getOwnPropertyNames(obj).forEach(key=>{
totalKey = `${totalKey}${ key}`+'.';
if(typeof obj[key] == 'object'){
convertObj(obj[key], totalKey);
}else {
totalKey.substr(0,totalKey.length-1)
result[totalKey.substr(0,totalKey.length-1)] = obj[key];
}
})
return result
}
console.log(convertObj(entry,totalKey));
var output = {}
function conver(obj,next) {
var next = next || ''
if (obj instanceof Object && obj.constructor.name === 'Object' ) {
for(var key in obj) {
conver(obj[key], next ? `${next}.${key}`: `${key}`)
}
} else {
if (next) {
output[next] = obj
} else {
throw '非法的数据类型!'
}
}
}
- 挺冗余的
var test = function (input) {
var output = {};
function copyCore(subObj, inputKey, output) {
var keyList = Object.keys(subObj);
var len = keyList.length;
for (var i = 0; i < len; i++) {
if (typeof subObj[keyList[i]] == 'object') {
if (inputKey == '') {
copyCore(subObj[keyList[i]], keyList[i], output);
}
else {
copyCore(subObj[keyList[i]], inputKey + '.' + keyList[i], output);
}
}
else {
if (inputKey == '') {
output[inputKey + keyList[i]] = subObj[keyList[i]];
}
else {
output[inputKey + "." + keyList[i]] = subObj[keyList[i]];
}
}
}
}
copyCore(input, '', output);
return output;
};
标准的backtracking解法。
var entry = {
a: {
b: {
c: {
dd: 'abcdd'
}
},
d: {
xx: 'adxx'
},
e: 'ae'
}
}
let _entry = {};
function flatten(obj, key_arr) {
for (let key in obj) {
key_arr.push(key)
if (typeof obj[key] !== 'object') {
_entry[key_arr.join('.')] = obj[key];
} else {
flatten(obj[key], key_arr)
}
key_arr.pop();
}
}
flatten(entry, [])
console.log(_entry)
我先来
function flatObj(obj, parentKey = "", result = {}) { for (const key in obj) { if (obj.hasOwnProperty(key)) { let keyName = `${parentKey}${key}`; if (typeof obj[key] === 'object') flatObj(obj[key], keyName+".", result) else result[keyName] = obj[key]; } } return result; }
使用 typeof 判断是否是 object 有些不妥, 值为 null 的时候会出错
判断都不做了。。
function entries(obj, preKey = '',result = {}){
for(let [key, value] of Object.entries(obj)){
const realKey = preKey ? `${preKey}.${key}` : key
if(typeof value === 'object'){
entries(value, realKey, result)
} else {
result[realKey] = value
}
}
return result
}
/* 解答 */
const toString = (item) => Object.prototype.toString.call(item)
const result = {}; // 结果容器
const transform = (target, key=[]) => {
if (toString(target) === '[object String]') {
const newKey = key.join('.');
const newValue = target;
Object.assign(result, {
[newKey]: newValue
})
return; // 终止递归,输出值
}
else {
Object.keys(target).forEach(item => {
transform(target[item], [].concat(key,item)); // 递归执行,保存key
})
}
}
transform(entry);
console.log(result);
觉得自己的代码仍然可以优化,另外问一句各位大佬,这里的代码高亮是如何做的?
今天的编程题呢?
我先来
function flatObj(obj, parentKey = "", result = {}) { for (const key in obj) { if (obj.hasOwnProperty(key)) { let keyName = `${parentKey}${key}`; if (typeof obj[key] === 'object') flatObj(obj[key], keyName+".", result) else result[keyName] = obj[key]; } } return result; }
换了一种方法:
function loop(entry, key = '', result = {}) {
const obj = Object.keys(entry);
for (let i = 0; i < obj.length; i++) {
const keyName = key + obj[i];
if (typeof entry[obj[i]] === 'object') {
this.loop(entry[obj[i]], `${keyName}.`, result);
} else {
result[keyName] = entry[obj[i]];
}
}
return result;
}
function getMyFlat(entry, parent= '', result ={}) {
for (let key in entry) {
if (entry.hasOwnProperty(key)) {
if(Object.prototype.toString.call(entry[key]) === '[object Object]') {
getMyFlat(entry[key], `${parent}${key}.`, result)
} else {
result[`${parent}${key}`] = entry[key]
}
}
}
return result;
}
console.log(getMyFlat(entry));
菜鸟版
const converst = (obj, result, valStr) => {
const keys =Object.keys(obj);
keys.forEach(function(i) {
if (typeof(obj[i]) === 'object') {
const val = `${valStr}${i}.`;
const objInfo = Object.keys(obj[i]);
converst(obj[i], result, val);
}
else {
const val = `${valStr}${i}`;
result[val] = obj[i];
}
});
return result;
}
let values = {};
let valStr = '';
const output = converst(entry, values, valStr);
console.log(output);
const entry = {
a: {
b: {
c: {
dd: 'abcdd'
}
},
d: {
xx: 'adxx'
},
e: 'ae'
}
};
function isObject (obj) {
return Object.prototype.toString.call(obj) === '[object Object]'
}
function flatObject(obj, key) {
if( !isObject(obj) ){
const o = {};
o[key] = obj;
return o;
}
const keys = Object.keys(obj);
const oo = {};
for (let i=0;i<keys.length;i++) {
const k = keys[i];
const o = flatObject(obj[k], key?(key+'.'+k):k);
Object.assign(oo, o);
}
return oo;
}
const o = flatObject(entry);
console.log(o);
var entry = {
a: {
b: {
c: {
dd: 'abcdd'
}
},
d: {
xx: 'adxx'
},
e: 'ae'
}
}
// 要求转换成如下对象
var output = {
'a.b.c.dd': 'abcdd',
'a.d.xx': 'adxx',
'a.e': 'ae'
}
function func(obj) {
let res = {}
let queue = [{
prop: "",
value:obj
}]
while (queue.length) {
let {prop,value} = queue.shift()
Object.keys(value).forEach(key => {
if (typeof value[key] === 'object') {
queue.push({
prop: `${prop}${prop && "."}${key}`,
value: value[key]
})
}else{
res[`${prop}${prop && "."}${key}`] = value[key]
}
})
}
return res
}
console.log(func(entry))
使用队列的方式进行广度遍历,性能比递归遍历更好,同时大大减少爆栈的风险
var entry = { a: { b: { c: { dd: 'abcdd' } }, d: { xx: 'adxx' }, e: 'ae' } } // 要求转换成如下对象 var output = { 'a.b.c.dd': 'abcdd', 'a.d.xx': 'adxx', 'a.e': 'ae' } function func(obj) { let res = {} let queue = [{ prop: "", value:obj }] while (queue.length) { let {prop,value} = queue.shift() Object.keys(value).forEach(key => { if (typeof value[key] === 'object') { queue.push({ prop: `${prop}${prop && "."}${key}`, value: value[key] }) }else{ res[`${prop}${prop && "."}${key}`] = value[key] } }) } return res } console.log(func(entry))使用队列的方式进行广度遍历,性能比递归遍历更好,同时大大减少爆栈的风险
挺简洁的
var entry = { a: { b: { c: { dd: 'abcdd' } }, d: { xx: 'adxx' }, e: 'ae' } } // 要求转换成如下对象 var output = { 'a.b.c.dd': 'abcdd', 'a.d.xx': 'adxx', 'a.e': 'ae' } function func(obj) { let res = {} let queue = [{ prop: "", value:obj }] while (queue.length) { let {prop,value} = queue.shift() Object.keys(value).forEach(key => { if (typeof value[key] === 'object') { queue.push({ prop: `${prop}${prop && "."}${key}`, value: value[key] }) }else{ res[`${prop}${prop && "."}${key}`] = value[key] } }) } return res } console.log(func(entry))使用队列的方式进行广度遍历,性能比递归遍历更好,同时大大减少爆栈的风险
想问一下,当函数实现了尾递归的情况下,就此题来说,队列遍历和递归遍历的性能如何比较,哪一方更具优势?
var entry = { a: { b: { c: { dd: 'abcdd' } }, d: { xx: 'adxx' }, e: 'ae' } } // 要求转换成如下对象 var output = { 'a.b.c.dd': 'abcdd', 'a.d.xx': 'adxx', 'a.e': 'ae' } function func(obj) { let res = {} let queue = [{ prop: "", value:obj }] while (queue.length) { let {prop,value} = queue.shift() Object.keys(value).forEach(key => { if (typeof value[key] === 'object') { queue.push({ prop: `${prop}${prop && "."}${key}`, value: value[key] }) }else{ res[`${prop}${prop && "."}${key}`] = value[key] } }) } return res } console.log(func(entry))使用队列的方式进行广度遍历,性能比递归遍历更好,同时大大减少爆栈的风险
想问一下,当函数实现了尾递归的情况下,就此题来说,队列遍历和递归遍历的性能如何比较,哪一方更具优势?
说一说我的理解吧,不对的地方还请指正
结论:我认为在实现了尾递归的情况下,队列遍历的性能还是要好一点。
- 原因:递归之所以会效率不高,是它执行的时候依赖子问题,所以在执行树上,会有很多相同的节点,我认为函数尾调用实现了将那些子问题当做中间变量保存了起来,当做该函数新的参数继续调用,那么它实现就和层次遍历所需要做的操作次数是差不多的。但是尾调用也会开辟新的函数执行环境,但N的数量达到一定程度,频繁创建和销毁函数执行环境也是需要一定时间吧,而队列遍历只要开辟一次函数执行环境。
let entry:object = {
a: {
b: {
c: {
dd: 'abcdd'
}
},
d: {
xx: 'adxx'
},
e: 'ae'
}
}
function handle (entry:object, arr:object, str:string):object {
for(let index of Object.keys(entry)) {
// console.log(entry[index])
if(entry[index] instanceof Object) {
handle(entry[index], arr, str.concat(`.${index}`))
} else {
arr[str.concat(`.${index}`).slice(1)] = entry[index]
console.log(arr)
}
}
return arr
}
let arr = handle(entry, [], '')
重在参与
function isObj(type) {
return Object.prototype.toString.call(type) === '[object Object]';
}
function trans(item, prefix = '', result = {}) {
for (let i in item) {
let key = `${prefix}${i}`;
isObj(item[i])
? trans(item[i], `${key}.`, result)
: (result[key] = item[i]);
}
return result;
}
const result = Object.create(null)
function transfer(entry, lastKey='') {
Object.entries(entry).forEach(([key, value]) => {
if (typeof value === 'object') {
transfer(value, `${lastKey}.${key}`);
} else {
result[`${(lastKey+'.'+key).replace(/^./, '')}`] = value
}
})
return result;
}
/**
* 将深层次的对象展平
* @param obj 要展平的对象
* @param str 传入的键值,第一次不传,用于递归
* @param res 要返回的对象,第一次不传
* @example
* flattenObj({
* a: {
* b: {
* c: 12
* }
* }
* }) // return { a.b.c: 12 }
*/
function flattenObj(obj, str, res) {
res = res || {}
function isObject(obj) {
return Object.prototype.toString.call(obj) === '[object Object]'
}
Object.keys(obj).forEach(key => {
let k = str ? str + '.' + key : key
if (isObject(obj[key])) {
return get(obj[key], k, res)
} else {
res[k]= obj[key]
}
})
return res
}
function getObj(entry) {
let out = {}
let keyStr = ''
if (!(entry instanceof Object)) {
return {}
}
Object.keys(entry).forEach((key) => {
split(keyStr, key, entry[key])
})
return out;
}
function split(keyStr, key, valueObj) {
keyStr += ${key}.
if (valueObj instanceof Object) {
Object.keys(valueObj).forEach((item) => {
if (valueObj instanceof Object) {
split(keyStr, item, valueObj[item])
}
})
} else {
out[keyStr.slice(0, keyStr.length - 1)] = valueObj
}
}
这道题是典型的DFS。这里有个技巧,就是将res作为参数传过去,
从而子函数(helper)可以对其进行修改。 这样我们可以不必依赖返回值,
也就避免了很多判断。
function helper(entry, prefix, res) {
for (const key in entry) {
if (entry[key] instanceof Object) {
helper(entry[key], `${prefix}.${key}`, res);
} else {
res[`${prefix.slice(1)}.${key}`] = entry[key];
}
}
}
function format(entry) {
const res = {};
helper(entry, "", res);
return res;
}
如果大家对数据结构和算法感兴趣,欢迎关注我的仓库
let entry = {
a: {
b: {
c: {
dd: 'abcdd'
}
},
d: {
xx: 'adxx'
},
e: 'ae'
}
};
let map = {};
function test(obj) {
Object.keys(obj).forEach((v, k)=> {
convertV(v, obj[v]);
});
}
function convertV(key, value) {
Object.keys(value).forEach((k,i) => {
if(typeof value[k] != 'object') {
map[key + '.' + k] = value[k];
} else if(value[k]){
convertV(key + '.' + k, value[k]);
}
});
}
test(entry);
console.log(map);
const transform = (obj, [...arr]) => {
let res = {};
let num = 0;
for (k in obj) {
if (num > 0) {
arr.pop()
}
arr.push(k)
num++;
if (typeof obj[k] === "object") {
Object.assign(res, transform(obj[k], arr))
} else {
res[arr.join(".")] = obj[k]
}
}
return res
}
回溯就完事了,感觉这种树形结构都可以暴力回溯解决,虽然效率不高
function fn(o) {
let res = {};
let choices = o;
bt('', choices)
function bt(trace, choices) {
if (typeof choices === 'string') {
res[trace] = choices;//如果路径触达叶端,碰到字符串类型,则获得一个结果
} else {
//否则继续探索路径
for (let k in choices) {
trace += k + '.';//前进一步
bt(trace, choices[k]);递归
trace = trace.substr(0, trace.length - 2);//后退一步 回溯
}
}
}
return res;
}
let keyarr = []; const output = {};
function transform(obj) {
for (let k in obj) {
keyarr.push(k);
if (typeof obj[k] === "object") {
transform(obj[k]);
} else {
output[keyarr.join('.')] = obj[k];
keyarr = [keyarr[0]];
}
}
}
transform(entry);
console.log('output', output);
function forMat(entry) {
let res = {}
function recur(obj, path = []) {
if (typeof obj == 'object' && obj != null) {
Object.keys(obj).forEach(key => {
recur(obj[key], path.concat(key))
})
} else {
let attr = path.join('.');
let val = obj;
res[attr] = val;
}
}
recur(entry);
return res;
}
function forMat(entry) {
let res = {}
function recur(obj, path = []) {
if (typeof obj == 'object' && obj != null) {
Object.keys(obj).forEach(key => {
recur(obj[key], path.concat(key))
})
} else {
let attr = path.join('.');
let val = obj;
res[attr] = val;
}
}
recur(entry);
return res;
}
本质上是递归遍历一棵树:
function getObj(obj, inKey = '' , res = {}) {
for (let key in obj) {
if (typeof obj[key] === 'object') {
getObj(obj[key], inKey==='' ? (key + '.') : inKey + key + '.', res)
} else {
res[ inKey + key ] = obj[key]
}
}
console.log(res, 'kevinnnnn')
return res
}
var entry = {
a: {
b: {
c: {
dd: 'abcdd'
}
},
d: {
xx: 'adxx'
},
e: 'ae'
}
}
function transform(obj) {
let output = {}
fn(obj)
return output
function fn(obj, temp_key = '') { //temp_key--临时存放属性名
for (let key in obj) {
if (typeof obj[key] == "object") {
fn(obj[key], temp_key + key + ".")
} else {
output[temp_key + key] = obj[key]
}
}
}
}
console.log(transform(entry)) //打印测试
思路:递归遍历,并用一个栈来保存路径
var entry = {
a: {
b: {
c: {
dd: 'abcdd',
},
},
d: {
xx: 'adxx',
},
e: 'ae',
},
};
// 要求转换成如下对象
var output = {
'a.b.c.dd': 'abcdd',
'a.d.xx': 'adxx',
'a.e': 'ae',
};
// 递归遍历,并用一个栈来保存路径
function convert(entry) {
const stack = [];
const output = {};
function each(obj) {
let keys = Object.keys(obj);
for (let key of keys) {
stack.push(key); // 入栈
if (isObject(obj[key])) { // 非末节点,继续递归
each(obj[key]);
} else { // 末节点,添加路径到output
output[stack.join('.')] = obj[key];
}
stack.pop(); // 出栈
}
}
each(entry);
return output;
}
function isObject(o) {
return Object.prototype.toString.call(o).slice(8, -1) === 'Object';
}
console.log(JSON.stringify(convert(entry), null, 4));
// 输出:
// {
// "a.b.c.dd": "abcdd",
// "a.d.xx": "adxx",
// "a.e": "ae"
// }
var res = {}
function entryObj(entry, keyi = "") {
for (var key in entry) {
if (typeof entry[key] === "object") {
entryObj(entry[key], keyi + key + ".")
} else {
console.log(keyi + key, entry[key])
res[keyi + key] = entry[key]
}
}
}
entryObj(entry)
console.log(res)
整体思路:递归深入获取属性字符串,闭包保存拼接的字符串,每次递归结束则去除遍历的属性值
function changeObj() {
let attr = []
const output = {}
return function checkAttr(obj) {
for(let k in obj) {
if(Object.prototype.toString.call(obj[k]) == '[object Object]') {
attr.push(k)
checkAttr(obj[k])
attr.pop()
} else {
attr.push(k)
const prop = attr.join('.')
output[prop] = obj[k]
attr.pop()
}
}
return output
}
}
console.log(changeObj()({
a: {
b: {
c: {
dd: 'abcdd'
},
f: {
k:'jskw',
g:'sdaw1'
}
},
d: {
xx: 'adxx'
},
e: 'ae'
}
}))
// 递归
function cook(entry, keyStr, res) {
for (const key in entry) {
const value = entry[key];
if (typeof value === 'string') {
res[keyStr + key] = value;
} else {
cook(value, `${keyStr + key}.`, res);
}
}
return res;
}
//bfs
function bfs(entry) {
const queue = [];
const res = {};
if (entry) {
queue.push({
keyList: '',
value: entry
});
while (queue.length > 0) {
const { keyList, value } = queue.shift();
Object.keys(value).forEach(key => {
const _key = `${keyList}${keyList && '.'}${key}`;
const _value = value[key];
if (typeof _value === 'string') {
res[_key] = _value;
} else {
queue.push({
keyList: _key,
value: _value
});
}
});
}
}
return res;
}
// dfs
function dfs(entry) {
const stack = [];
const res = {};
if (entry) {
stack.push({
keyList: '',
value: entry
});
while (stack.length > 0) {
const { keyList, value } = stack.shift();
const keys = Object.keys(value);
for(let i=keys.length-1;i>=0;i--){
const key = keys[i]
const _key = `${keyList}${keyList && '.'}${key}`;
const _value = value[key];
if (typeof _value === 'string') {
res[_key] = _value;
} else {
stack.unshift({
keyList: _key,
value: _value
});
}
}
}
}
return res;
}
对象的扁平化,没有说数组和空对象怎么处理,那就按默认处理了
function flatten(input) {
let result = {};
let re = function(key,obj){
if(obj instanceof Object && !(obj instanceof Array)){
let empty = true;
for(let index in obj){
empty = false;
re(key ? `${key}.${index}` : index,obj[index]);
}
if(empty && key){
result[key] = {};
}
}else{
result[key] = obj;
}
};
re('',input);
return result;
}
function transform(target, keyList=[], result={}) {
if(typeof target === 'string'){
result[keyList.join('.')] = target
}else{
Object.keys(target).forEach((key)=>{
transform(target[key], [...keyList, key], result)
})
}
return result
}
var entry = {
a: {
b: {
c: {
dd: 'abcdd'
}
},
d: {
xx: 'adxx'
},
e: 'ae'
},
b: 1
}
console.log('trans(entry): ', trans(entry));
function trans(obj) {
var output = {};
temp(obj, output, '');
function temp(obj, output = {}, key = '') {
for (var [k, v] of Object.entries(obj)) {
if (typeof v != 'object') {
output[key + k] = v;
} else {
temp(v, output, key + k + '.');
}
}
};
return output;
}
遍历树
var entry = {
a: {
b: {
c: {
dd: 'abcdd'
}
},
d: {
xx: 'adxx'
},
e: 'ae'
},
hh: [{
aa: 'aa'
}]
}
function bar2(obj, parentKey) {
let nodes = []
Object.keys(obj).forEach(key => {
let parentKeyNext = parentKey ? `${parentKey}.${key}` : key
if(typeof obj[key] === 'object') {
nodes = nodes.concat(bar2(obj[key], parentKeyNext))
} else {
nodes.push({
parentKey: parentKeyNext,
val: obj[key]
})
}
})
return nodes
}
console.log(bar2(entry, ''))
/*
[
{ parentKey: 'a.b.c.dd', val: 'abcdd' },
{ parentKey: 'a.d.xx', val: 'adxx' },
{ parentKey: 'a.e', val: 'ae' },
{ parentKey: 'hh.0.aa', val: 'aa' }
]
*/
function flatObj(obj,key='',result={}){
if(typeof obj !== 'object' || obj===null){
result[key] = obj
return
}
Object.keys(obj).forEach(k=>{
flatObj(obj[k], `${key}${key?'.':''}${k}`,result)
})
return result
}
function flagObj(obj, key = '', res = {}) {
if (typeof obj != 'object' || !obj) {
res[key] = obj
} else {
for (let k in obj) {
flagObj(obj[k], `${key ? key + '.' : key}${k}`, res)
}
}
return res
}
const isObj = (a) => typeof a === 'object' && a !== null;
const simpleObj = (obj) => {
const stack = [obj];
let current;
const out = {};
const _p = Symbol('_p');
const _pNode = Symbol('_pNode');
while(stack.length) {
current = stack.pop();
if (isObj(current)) {
Object.keys(current).reverse().forEach(key => {
stack.push(current[key]);
if (!isObj(current[key])) {
let temp = key;
let currentTemp = current;
while(currentTemp && currentTemp[_p]) {
temp = `${currentTemp[_p]}.${temp}`;
currentTemp = currentTemp[_pNode];
}
out[temp] = current[key];
} else {
current[key][_pNode] = current;
current[key][_p] = key;
}
});
}
}
return out;
}
var entry = {
a: {
b: {
c: {
dd: 'abcdd'
}
},
d: {
xx: 'adxx'
},
e: 'ae'
}
}
console.log(simpleObj(entry));
function transformObj(obj) {
const newObj = {}
const objArray = []
const topKey = Reflect.ownKeys(obj).shift()
const firstKey = obj[topKey]
Reflect.ownKeys(firstKey).forEach((key) => objArray.push(JSON.stringify({ [key]: firstKey[key] })))
const resultArray = objArray.map((item) => item.replace(/{|"|}|/g, ''))
resultArray.forEach((item) => {
const key = item.split(':')
const value = key.pop()
newObj[topKey + '.' + key.toString().replace(/,/g, '.')] = value
})
return newObj
}
transformObj(entry)
思路是解析为字符串再转换
var entry = {
a: {
b: {
c: {
dd: 'abcdd'
}
},
d: {
xx: 'adxx'
},
e: 'ae'
}
}
function change(entry, fkey = '', res = {}){
if(typeof entry != 'object'){
res[fkey] = entry
return
}
for(let key in entry){
if(fkey !== ''){
change(entry[key], `${fkey}.${key}`, res)
}else{
change(entry[key], `${key}`, res)
}
}
return res
}
console.log(change(entry))
bfs
function flatObj(entry) { const queue = Object.entries(entry) const res = {} while (queue.length) { const [key, obj] = queue.pop() for (const [k, v] of Object.entries(obj)) { if (typeof v !== 'object') { res[`${key}.${k}`] = v } else { queue.push([`${key}.${k}`, v]) } } } return res }
bfs的话应该queue.shift(),另外没考虑{a:1}这种情况,按你代码输出是{},简单修改下:
function flatObj(entry) {
const queue = Object.entries(entry)
const res = {}
while (queue.length) {
const [key, obj] = queue.shift()
if (typeof obj === 'object') {
for (const [k, v] of Object.entries(obj)) {
queue.push([`${key}.${k}`, v])
}
} else {
res[key] = obj
}
}
return res
}
function flatObj(obj) {
let res = {}
function dfs(str, obj) {
if (typeof obj !== 'object') {
res[str] = obj
return
}
for (let i in obj) {
let s = str === '' ? i : `${str}.${i}`
dfs(s, obj[i])
}
}
dfs('', obj)
return res
}
function isObject(obj) {
return Object.prototype.toString.call(obj) === '[object Object]'
}
function parseToObj(obj, paths = []) {
if (!isObject(obj)) {
return paths.length > 0
? { [paths.join('.')]: obj }
: obj
}
return Object.keys(obj).reduce((res, key) => {
Object.assign(res, parseToObj(obj[key], paths.concat(key)))
return res
}, {})
}
const testObj = {
a: {
b: {
c: {
dd: 'abcdd'
}
},
d: {
xx: 'adxx'
},
e: 'ae'
}
}
console.log(parseToObj(testObj))
function hadnler(entry, str = "", map = {}) {
Object.keys(entry).forEach(item => {
const res = entry[item]
if (typeof res != "object") {
map[str + item] = res
} else {
hadnler(res, str + item + ".", map)
}
})
return map
}
function convert(entry) {
let obj = {};
helper(entry, "", obj);
return obj
}
function helper(entry, pKey, obj) {
for (const key in entry) {
if (typeof entry[key] == "string") {
let keyname = `${pKey}${key}`;
obj[keyname] = entry[key];
} else {
helper(entry[key], `${pKey}${key}.`, obj);
}
}
}
const trans = (entry) => {
let outPut = {}
const run = (entry, name = '') => {
const keys = Object.keys(entry)
for(let key of keys) {
let v = entry[key]
let t = name ? `${name}.${key}` : key
if(typeof v !== 'object') {
outPut[t] = v
}else {
run(v, t)
}
}
}
run(entry)
return outPut
}
trans(entry)
function format(entry) {
const result = {}
recur(entry)
return result
function recur(obj, path = []) {
Object.keys(obj).forEach((key) => {
const value = obj[key]
if (typeof value === 'object') {
recur(value, [...path, key])
} else {
const id = path.length ? `${path.join(".")}.${key}` : key
result[id] = value;
}
})
}
}
var entry = {
a: {
b: {
c: {
dd: "abcdd",
},
},
d: {
xx: "adxx",
},
e: "ae",
},
};
console.log("debug-", format(entry));
function objTransitionStr(entry) {
const res = {};
const _helper = (obj, key = "") => {
if (typeof obj !== "object") {
res[key.slice(1)] = obj;
return;
}
const keys = Object.keys(obj);
const values = Object.values(obj);
for (let i = 0; i < keys.length; i++) {
_helper(values[i], `${key}.${keys[i]}`);
}
};
_helper(entry);
return res;
}
// 递归解法
var entry = {
a: {
b: {
c: {
dd: 'abcdd'
}
},
d: {
xx: 'adxx'
},
e: 'ae'
}
}
// 要求转换成如下对象
var output = {
'a.b.c.dd': 'abcdd',
'a.d.xx': 'adxx',
'a.e': 'ae'
}
function transform(entry) {
let output = {};
function _inner(target, path) {
if (target === null || typeof target !== 'object') {
return output[path] = target;
}
Reflect.ownKeys(target).forEach(key => {
_inner(target[key], path ? `${path}.${key}` : `${key}`);
});
}
_inner(entry, '');
return output;
}
console.log(transform(entry));
function flatObj(obj) {
var res = {}
function dfs(obj, preKey = '') {
Reflect.ownKeys(obj).forEach(key => {
var keyName = `${preKey}${key}`
if(typeof obj[key] === 'object') {
dfs(obj[key], keyName + '.')
} else {
res[keyName] = obj[key]
}
})
}
dfs(obj)
return res
}
flatObj(entry)
/**
* 1. 对象扁平化
*/
function flat(obj, pre = '', result = {}) {
Object.keys(obj).forEach((v) => {
const key = `${preKey}${v}`
if (typeof obj[v] === 'object') {
flat(obj[v], `${key}.`, result)
} else {
result[key] = obj[v]
}
})
return result
}
const flatResult = flat(entry, '', {})
console.log(flatResult)
/**
* 2. 扁平化对象重组
*/
function restore(obj) {
let result = {}
Object.keys(obj).forEach((v) => {
const list = v.split('.')
const value = obj[v]
list.reduce((res, item, index) => {
if (index === list.length - 1) {
res[item] = value
} else {
res[item] = res[item] ? res[item] : {}
}
return res[item]
}, result)
})
return result
}
console.log(JSON.stringify(restore(flatResult), null, 4))
const find666 = (entry) => {
let map = {}
//递归方式
let func = (val, pname) => {
for (key in val) {
let kname = `${key}`
if (pname) {
kname = `${pname}.${key}`
}
if (typeof val[key] === 'object') {
func(val[key], kname)
} else {
map[kname] = val[key]
}
}
}
func(entry)
}
利用构造函数
function toObject(entry, output = {}, k_name = '') {
for (let key in entry) {
if (entry[key].constructor == Object){
toObject(entry[key], output, k_name ? `${k_name}.${key}` : `${key}`);
}else{
output[`${k_name}.${key}`] = entry[key];
}
}
return output
}
toObject(entry)
回溯解决
var entry = {
a: {
b: {
c: {
dd: 'abcdd'
}
},
d: {
xx: 'adxx'
},
e: 'ae'
}
}
function trans(obj) {
const result = {};
for (let k in obj) {
backtrace([k])
}
function backtrace(trace) {
let o = obj;
for (let i = 0; i < trace.length; i++) {
o = o[trace[i]]
}
if (typeof o !== 'object') {
result[trace.join(',')] = o;
return;
}
for (let k in o) {
trace.push(k);
backtrace(trace);
trace.pop();
}
}
return result;
}
console.log(trans(entry))
function flatten(obj) {
var res = {};
function flat(obj, key) {
if (obj === null || Object(obj) !== obj) {
res[key] = obj;
} else if (Array.isArray(obj)) {
var len = obj.length;
if (len < 1) {
res[key] = [];
return;
}
for (var i = 0; i < len; i++) {
flat(obj[i], key ? `${key}[${i}]` : key + '');
}
} else {
for (var k in obj) {
flat(obj[k], key ? `${key}.${k}` : k);
}
}
}
flat(obj, '');
return res;
}
var obj = {
a: {
b: 1,
c: 2,
d: {
e: 5
}
},
b: [1, 3, {
a: 2,
b: 3
}],
c: 3
}
flatten(obj)
var entry = {
a: {
b: {
c: {
dd: 'abcdd'
}
},
d: {
xx: 'adxx'
},
e: 'ae'
}
}
function flatObj(obj, preKey = '') {
let res = {};
for (let key in obj) {
let value = obj[key];
let newKey = preKey ? `${preKey}.${key}` : key;
if (typeof obj[key] === 'object') {
flatObj(obj[key], newKey)
} else {
res[newKey] = value;
}
}
}
console.log(flatObj(entry))
function(tree){ const res = new Map() function main(tree, preKey = ''){ const keys = Object.keys(tree) for(let i = 0; i < keys.length; i++){ if(typeof tree[keys[i]] === 'object'){ main(tree[keys[i]], preKey ?
${preKey}.${keys[i]} : keys[i]) }else{ res.set(
${preKey}.${keys[i]}, tree[keys[i]]) } } } main(tree) return res }