Daily-Interview-Question
Daily-Interview-Question copied to clipboard
第 111 题:编程题,写个程序把 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 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); 不用闭包是不完美的!