Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

第 112 题:编程题,写个程序把 entry 转换成如下对象 #212

Open
yygmind opened this issue Jul 24, 2019 · 84 comments
Open

第 112 题:编程题,写个程序把 entry 转换成如下对象 #212

yygmind opened this issue Jul 24, 2019 · 84 comments

Comments

@yygmind
Copy link
Contributor

yygmind commented Jul 24, 2019

var entry = {
  'a.b.c.dd': 'abcdd',
  'a.d.xx': 'adxx',
  'a.e': 'ae'
}

// 要求转换成如下对象
var output = {
  a: {
   b: {
     c: {
       dd: 'abcdd'
     }
   },
   d: {
     xx: 'adxx'
   },
   e: 'ae'
  }
}
@MoveZZG
Copy link

MoveZZG commented Jul 24, 2019

我继续先来

 var entry = {
    'a.b.c.dd': 'abcdd',
    'a.d.xx': 'adxx',
    'a.e': 'ae'
  }

  function map(entry) {
    const obj = Object.create(null);
    for (const key in entry) {
      const keymap = key.split('.');
      set(obj, keymap, entry[key])
    }
    return obj;
  }

  function set(obj, map, val) {
    let tmp;
    if (!obj[map[0]]) obj[map[0]] = Object.create(null);
    tmp = obj[map[0]];
    for (let i = 1; i < map.length; i++) {
      if (!tmp[map[i]]) tmp[map[i]] = map.length - 1 === i ? val : Object.create(null);
      tmp = tmp[map[i]];
    }
  }
  console.log(map(entry));

@magicds
Copy link

magicds commented Jul 24, 2019

题目

// 输入
var entry = {
    'a.b.c.dd': 'abcdd',
    'a.d.xx': 'adxx',
    'a.e': 'ae'
};

// 要求转换成如下对象
var output = {
    a: {
        b: {
            c: {
                dd: 'abcdd'
            }
        },
        d: {
            xx: 'adxx'
        },
        e: 'ae'
    }
};

实现思路

遍历对象,如果键名称含有 . 将最后一个子键拿出来,构成对象,如 {'a.b.c.dd': 'abcdd'} 变为 {'a.b.c': { dd: 'abcdd' }} , 如果变换后的新父键名中仍还有点,递归进行以上操作即可。

// 输入
{
    'a.b.c.dd': 'abcdd',
    'a.d.xx': 'adxx',
    'a.e': 'ae'
}
// 1
t1 = {
    'a.b.c': { dd: 'abcdd' },
    'a.d': { xx: 'adxx' },
    a: { e: 'ae' }
};
// 2
// t1 = {
//     'a.b': { c: { { dd: 'abcdd' } },
//     a: { d: { { xx: 'adxx' } },
//     a: { e: 'ae' }
// };
// a.d 属性进行拆分时 需要新加入父键 a 而a已经存在 则进行合并
t2 = {
    'a.b': { c: { dd: 'abcdd' } },
    a: { e: 'ae', d: { xx: 'adxx' }  }
};
// 3
// t3 = {
//     'a': { b: { c: { dd: 'abcdd' } } },
//     a: { e: 'ae', d: { xx: 'adxx' }  }
// };
t3 = {
    a: { b: { c: { dd: 'abcdd' } }, e: 'ae', d: { xx: 'adxx' }  }
};

代码

function nested(obj) {
    Object.keys(obj).map(k => {
        getNested(k);
    });

    return obj;

    function getNested(key) {
        const idx = key.lastIndexOf('.');
        const value = obj[key];
        if (idx !== -1) {
            delete obj[key];
            const mainKey = key.substring(0, idx);
            const subKey = key.substr(idx + 1);
            if (obj[mainKey] === undefined) {
                obj[mainKey] = { [subKey]: value };
            } else {
                obj[mainKey][subKey] = value;
            }
            if (/\./.test(mainKey)) {
                getNested(mainKey);
            }
        }
    }
}

console.log(JSON.stringify(nested(entry), 0, 2));

@j-colter
Copy link

const func2 = (input, output = {}) => {
  const generateKeys = (key, value, output = {}) => {
    const index = key.indexOf('.')
    if (index > 0) {
      const s = key.substring(0, index)
      const e = key.substring(index + 1)
      if (!output[s]) output[s] = {}

      generateKeys(e, value, output[s])
    } else {
      output[key] = value
    }
  }

  for (const k in input) {
    generateKeys(k, input[k], output)
  }
}

const o2 = {}
const input = func2(entry, o2)
console.log('o2', JSON.stringify(o2))

@xubaifuCode
Copy link

var entry = {
    'a.b.c.dd': 'abcdd',
    'a.d.xx': 'adxx',
    'a.e': 'ae',
    'd.e.x': 'dex'
}
const obj = {};
Object.keys(entry).map((keyName) => {
    return keyName.split('.');
}).forEach(keysArr => {
    let currObj = obj;
    const keysArrLength = keysArr.length;
    for (let i = 0; i < keysArrLength; i += 1) {
        const keyItem = keysArr[i];
        if (!currObj[keyItem]) {
            currObj[keyItem] = i !== keysArrLength - 1 ? {} : entry[keysArr.join('.')];
        }
        currObj = currObj[keyItem];
    }
});
console.log(obj);

@lixianfeng1992
Copy link

var deFlat = function(entry) {
  const res = {};
  for (let key in entry) {
    const sequenceKey = key.split('.');
    format(res, sequenceKey, entry[key]);
  }
  return res;
}

var format = function(obj, sequenceKey, value) {
  const key = sequenceKey.shift();
  if (!sequenceKey.length) {
    obj[key] = value;
  } else {
    obj[key] = obj[key] || {};
    format(obj[key], sequenceKey, value);
  }
}

var entry = {
  'a.b.c.dd': 'abcdd',
  'a.d.xx': 'adxx',
  'a.e': 'ae'
}

console.log(deFlat(entry))

@ZTrainWilliams
Copy link

ZTrainWilliams commented Jul 24, 2019

var entry = {
    'a.b.c.dd': 'abcdd',
    'a.d.xx': 'adxx',
    'a.e': 'ae'
}
function setFlat (entry) {
    let res = {}
    function namespace(oNamespace, sPackage, value) {
        let iner = oNamespace
        let arr = sPackage.split('.')
        let len = arr.length
        arr.forEach((key, idx) => {
            iner = iner[key] = (idx === len - 1 ? value : (iner[key] instanceof Object ? iner[key] : {}))
        })
    }
    for (let k in entry) {
        namespace(res, k, entry[k])
    }
    return res
}
console.log(JSON.stringify(setFlat(entry)))
// {"a":{"b":{"c":{"dd":"abcdd"}},"d":{"xx":"adxx"},"e":"ae"}}

@flyfox11
Copy link

var entry = {
    'a.b.c.dd': 'abcdd',
    'a.d.xx': 'adxx',
    'a.e': 'ae'
}

function transObj(input) {
    let ouput = null
    let arr = Object.entries(input)
    arr.forEach((item,index)=>{
        let cellArr = item[0].split('.')
        let cellObj = {}
        let count = 0
        while(cellArr.length) {
            let key = cellArr.splice(-1)
            if(count == 0) {
                cellObj = {[key]:item[1]}
                count ++
            }else {
                if(ouput && ouput[key]) {
                    ouput[key] = Object.assign(ouput[key],cellObj)
                }else {
                    cellObj = {[key]:cellObj}
                }
                
            }  
        }
        if(!ouput) {
            ouput = cellObj
        }
    })
    return ouput
}

console.log(transObj(entry))

@RGXMG
Copy link

RGXMG commented Jul 24, 2019

实现思路:

  1. 对象entry的key中含有的.就是一个对象嵌套,所以可以用split()函数将其划分为一个array,所以array的length - 1下标所对应的元素就是entry的一个key的具体值。
  2. 利用对象为地址引用原理,进行增加元素。
  3. 采用reduce函数,将每一次的引用返回。
const entry = {
  'a.b.c.dd': 'abcdd',
  'a.d.xx': 'adxx',
  'a.e': 'ae',
};
const changObjStructureOfNormal = output => {
  const keys = Object.keys(output);
  const resObj = {};
  for (const key of keys) {
    const everyKey = key.split('.');
    everyKey.reduce((pre, next, index, array) => {
      if (index === array.length - 1) {
        pre[next] = output[key];
        return;
      }
      pre[next] = pre[next] || {};
      return pre[next];
    }, resObj);
  }
  return resObj;
};
changObjStructureOfNormal(entry);

@hpysirius
Copy link

hpysirius commented Jul 24, 2019

function changeToNormal(obj) {
    let newObj = {};
    let t = newObj;
    const keys = Object.keys(obj);
    for (key of keys) {
        const fArr = key.split('.');
        while (fArr.length) {
            const val = fArr.length === 1 ? entry[key] : {};
            const tmpKey = fArr.shift();
            t[tmpKey] = t[tmpKey] || val;
            t = t[tmpKey];
        }
        t = newObj;
    }
    return newObj;
}

@skyunBoss
Copy link

var entry = {
    'a.b.c.dd': 'abcdd',
    'a.d.xx': 'adxx',
    'a.e': 'ae'
}

function getOutput(obj) {
    let output = {};

    if (Object.prototype.toString.call(entry) === '[object Object]') {
        for (let i in obj) {
            let splitKey = i.split('.');

            (function getKeys(output, splitKey, value) {
                const key = splitKey.shift();
                if (!splitKey.length) {
                    output[key] = value;
                } else {
                    output[key] = output[key] || {};
                    getKeys(output[key], splitKey, value)
                }
            })(output, splitKey, obj[i])
        }
    } else {
        console.log('传入的不是对象');
    }

    return output;
}

getOutput(entry)

@suguoyao
Copy link

@RGXMG 我的实现思路和你这个一致,喜欢你这个👍

@Lostsory
Copy link

Lostsory commented Jul 24, 2019

var entry = {
      'a.b.c.dd': 'abcdd',
      'a.d.xx': 'adxx',
      'a.e': 'ae'
    }
    const tranfer = (o, r = {}) => {
      for (let i in o) {
        var a = i.split('.')
        var j = 0
        var stack = [{
          parent: r,
          key: a[j]
        }]
        while (stack.length) {
          var item = stack.pop()
          j ++
          if (a[j]) {
            if (!item.parent[item.key]) {
              item.parent[item.key] = {}
            }
            stack.push({
              parent: item.parent[item.key],
              key: a[j]
            })
          } else {
            item.parent[item.key] = o[i]
          }
        }
      }
      return r
    }

@weiweixuan
Copy link

 var entry = {
        'a.b.c.dd': 'abcdd',
        'a.d.xx': 'adxx',
        'a.e': 'ae'
      }

      function exchange(obj) {
        if (typeof obj != 'object') {
          throw new Error('请输入 [object Object] 类型')
        }
        // 对象转map
        let map = new Map()
        for (let key in obj) {
          let arr = key.split('.')
          map.set(arr, obj[key])
        }
        let O = {}
        let digui = function(map, object) {
          let obj = {}
          map.forEach((item, index, arr) => {
            // 取下标
            let key = index.shift(),
              length = index.length
            // 判断是否存在,不存在就添加
            if (!object[key]) {
              object[key] = length > 0 ? obj : item //判断是否为最后一个key,如果是就展示值,不是就继续递归
            }
            if (length > 0) {
              // 创建map结构
              let currMap = new Map()
              currMap.set(index, item)
              digui(currMap, object[key])
            }
          })
        }
        digui(map, O)
        return O
      }
      let res = exchange(entry)
      console.log(res)

@869288142
Copy link

869288142 commented Jul 24, 2019

var entry = {
  "a.b" : 111,
  "a.c" : 2222,
  "c.c" : 333,
  "c.a.c": 3333
}

let obj = {

}

for(let [path , v] of Object.entries(entry)) {
  let paths = path.split(".")
  let k;
  let cur = obj 
  // 最后一层路径
  let tail = paths.pop()
  // 迭代每层对象,在没有该路径情况下,创建,反之直接使用
  while(k = paths.shift()) {
    if(!cur[k]) {
      cur[k] = {
      
      }
    }
    // 切换到当前路径对象
    cur = cur[k]
  }
  // 将值赋值给最终位置
  cur[tail] = v 
}

console.log(obj);

@tangzhibao
Copy link

基本思路

我的思路:

  • 遍历每一个需要展开的key,按照层级将其插入结果容器中。
  • 首次出现的key则创建,重复出现则跳过,统一进入下一个层级。
  • 当剩余展开深度为0则赋值

看到很多大神的回复,觉得有更好的思路可以实现,感觉自己这个比较普普通通哈哈。

/* 2019-07-24 */
var entry = {
  'a.b.c.dd': 'abcdd',
  'a.d.xx': 'adxx',
  'a.e': 'ae'
}

var output = {
  a: {
    b: {
      c: {
        dd: 'abcdd'
      }
    },
    d: {
      xx: 'adxx'
    },
    e: 'ae'
  }
}

// 要求将entry转化为output对象 (与昨日相反)



/* 解答 */

/**
 * 
 * @param {Object} target 展开的key所插入的目标对象
 * @param {Array} key 剩余需展开的key的数组
 * @param {String} value 最终的值
 */
const transform = (target = {}, key = [], value = 0) => {
  if (!key.length) return;  // 终止递归
  const currentKey = key.splice(0, 1);  // 截取当前首位key
  if (!target[currentKey]){
    target[currentKey] = key.length=== 0 ? value : {} ;  // 若当前属性为首次出现,则在对应深度创建该属性并赋值为空对象;若无剩余展开key时赋值
  }
  transform(target[currentKey], key, value);  // 进入下一次递归
}

const result = {};  // 结果容器
const keys = Object.keys(entry);  // 对象所需展开的字符串key
keys.map(item => transform(result, item.split('.'), entry[item]));
console.log(result);

@xbsummer
Copy link

xbsummer commented Jul 24, 2019

var entry = {
 'a.b.c.dd': 'abcdd',
 'a.d.xx': 'adxx',
 'a.e': 'ae'
}
let obj = {};

for (let key of Object.keys(entry)) {
    key.split(".").reduce((s,c,i,a)=> {
        s[c] =  s[c] || (!a[i + 1] && entry[key]) || {};
        return s[c];
    }, obj);
}

console.log(JSON.stringify(obj));

@MissNanLan
Copy link

var obj = {
 'a.b.c.dd': 'abcdd',
 'a.d.xx': 'adxx',
 'a.e': 'ae'
}
function entery(obj){

 let result = {}
 
 Object.getOwnPropertyNames(obj).forEach(key=>{
   getObj(key,obj[key],result)
     
 })
 
 
 function getObj(key,value,res){
   console.log(res);
      let keyArr = []
      let _length;
      keyArr = key.split('.');
      _length = keyArr.length;
      keyArr.forEach((item,index)=>{
        if(index ==_length-1){
          res[item] = value
        }else {
          res[item] = res[item] instanceof Object ? res[item]: {};
        }
        res = res[item];
      })

   
 }
  return result;
}
console.log(entery(obj));

@fengtomy
Copy link

const transform = entry => { 
  const result = {}; 
  for (let prop in entry) { 
    if (entry.hasOwnProperty(prop)) { 
      if (~prop.indexOf(".")) { 
        const arr = prop.split("."); 
        let curr = result;
         while (arr.length > 1) { 
           const item = arr.shift(); 
           if (!curr[item]) { 
            curr[item] = {}; 
          } 
          curr = curr[item]; 
        } 
        curr[arr.shift()] = entry[prop]; 
      } else { 
        result[prop] = entry[prop]; 
      } 
    } 
  }
  return result; 
};

@zfowed
Copy link

zfowed commented Jul 25, 2019

实现

/** 将路径分解成数组 */
function pathToArray (path) {
  return Array.isArray(path) ? path : path.replace(/\[/g, '.').replace(/\]/g, '').split('.')
}

/** 设置 object对象中对应 `path` 属性路径上的值 */
function set (object, path, value) {
  path = pathToArray(path)
  path.reduce((data, key, index) => {
    if (index !== path.length - 1) {
      if (!data[key]) { data[key] = {} }
    } else {
      data[key] = value
    }
    return data[key]
  }, object)
}

测试

const entry = {
    'a.b.c.dd': 'abcdd',
    'a.d.xx': 'adxx',
    'a.e': 'ae'
}

const output = {}

for (const [key, value] of Object.entries(entry)) {
  set(output, key, value)
}

console.log(output)

@wingmeng
Copy link

var entry = {
  'a.b.c.dd': 'abcdd',
  'a.d.xx': 'adxx',
  'a.e': 'ae'
};

function formatEntryToTree(obj) {
  var output = {};
  var handle = function(keys, value) {
    keys.reduce(function(before, now, index) {
      before[now] = index === keys.length - 1 ? value : output[now] || {};
      return before[now];
    }, output);
  };

  for (var key in obj) {
    if (obj.hasOwnProperty(key)) {
      var keys = key.split('.');
      handle(keys, obj[key]);
    }
  }

  return output;
}

console.log(formatEntryToTree(entry));

@IAMSBLOL
Copy link

IAMSBLOL commented Jul 25, 2019

var output = {}
var getObject = (data) => {
    for (let [k, v] of Object.entries(entry)) {
        let kList = k.split('.')
        let evalStr = 'output'
        kList.map((o, i) => {
            if (kList.length - 1 === i) {
                evalStr = evalStr + '.' + o
                eval(`${evalStr}='${v}'`)
            } else {
		if(!output.hasOwnProperty(o)){
			evalStr = evalStr + '.' + o
			eval(`${evalStr}={}`)
		}
            }
        })
    }
}
getObject(entry)
console.log(output)

eval()大法实现,

@q77763429
Copy link

function convert (obj) {
	var returnObj = {};
	for (var key in obj) {
		var keyList = key.split('.');
		if (!returnObj[keyList[0]]) {
			returnObj[keyList[0]] = {};
		}
		var mapObj = returnObj[keyList[0]];
		for (var i = 1; i < keyList.length; i++) {
			var k = keyList[i];
			if (i === keyList.length - 1) {
				mapObj[k] = obj[key];
			} else {
				if (!mapObj[k]) {
					mapObj[k] = {};
				}
				mapObj = mapObj[k];
			}
		}
	}
	return returnObj;
}

对象是引用类型的想法

@pzjzeason
Copy link

pzjzeason commented Jul 26, 2019

@RGXMG

const entry = {
  'a.b.c.dd': 'abcdd',
  'a.d.xx': 'adxx',
  'a.e': 'ae',
};
const changObjStructureOfNormal = output => {
  const keys = Object.keys(output);
  const resObj = {};
  for (const key of keys) {
    const everyKey = key.split('.');
    everyKey.reduce((pre, next, index, array) => {
      if (index === array.length - 1) {
        pre[next] = output[key];
        return;
      }
      pre[next] = resObj[next] || {};
      return pre[next];
    }, resObj);
  }
  return resObj;
};
changObjStructureOfNormal(entry);

pre[next] = resObj[next] || {};错了,

const entry = {
    'a.b.c.dd': 'abcdd',
    'a.b.c.ee': 'abcee',
    'a.d.xx': 'adxx',
    'a.e': 'ae',
  };
// output: {"a":{"b":{"c":{"ee":"abcee"}},"d":{"xx":"adxx"},"e":"ae"}}
// 'a.b.c.dd': 'abcdd' 被覆盖

pre[next] = resObj[next] || {};应该改为 pre[next] = pre[next] || {};

@RGXMG
Copy link

RGXMG commented Jul 26, 2019

@pzjzeason

@RGXMG

const entry = {
  'a.b.c.dd': 'abcdd',
  'a.d.xx': 'adxx',
  'a.e': 'ae',
};
const changObjStructureOfNormal = output => {
  const keys = Object.keys(output);
  const resObj = {};
  for (const key of keys) {
    const everyKey = key.split('.');
    everyKey.reduce((pre, next, index, array) => {
      if (index === array.length - 1) {
        pre[next] = output[key];
        return;
      }
      pre[next] = resObj[next] || {};
      return pre[next];
    }, resObj);
  }
  return resObj;
};
changObjStructureOfNormal(entry);

pre[next] = resObj[next] || {};错了,

const entry = {
    'a.b.c.dd': 'abcdd',
    'a.b.c.ee': 'abcee',
    'a.d.xx': 'adxx',
    'a.e': 'ae',
  };
// output: {"a":{"b":{"c":{"ee":"abcee"}},"d":{"xx":"adxx"},"e":"ae"}}
// 'a.b.c.dd': 'abcdd' 被覆盖

pre[next] = resObj[next] || {};应该改为 pre[next] = pre[next] || {};

哈哈,好像是错了,估计是粘贴变量名的时候粘错了位置。感谢提醒

@btea
Copy link

btea commented Jul 26, 2019

function v(obj){
    let arr = Object.keys(obj);
    let $obj = {};
    arr.map(key => {
        let attrs = key.split('.');
        attrs.reduce((str, v) => {
            let s = `$obj.${str}`;
            if(!eval(s)){eval(`${s}={}`);}
            return str += '.' + v;
        });
        eval(`$obj.${key}=obj[key]`);
    });
    return $obj;
}

@negativeentropy9
Copy link

function transfer(entry) {
    const result = {}

    Object.entries(entry).forEach(([key, value]) => {
        const keyArr = key.split('.');

        result[keyArr[0]] = result[keyArr[0]] || {}
        let targetObj = result[keyArr[0]]

        for (let j = 1, length = keyArr.length; j < length; j++) {
            if (j < length - 1) {
                const tempObj = targetObj;
                
                targetObj = targetObj[keyArr[j]] || {}
                tempObj[keyArr[j]] = targetObj
            } else {
                targetObj[keyArr[j]] = value
            }
        }
    })

    return result;
}

@zhongdeming428
Copy link

zhongdeming428 commented Jul 29, 2019

function buildObj(obj) {
  let result = {}
  Object.keys(obj).forEach(key => {
    let stack = key.split('.'),
      res = result
    while(stack.length !== 0) {
      let k = stack.shift()
      if (!res.hasOwnProperty(k))
        res[k] = stack.length === 0 ? obj[key] : {}
      res = res[k]
    }
  })
  return result
}

@liyongleihf2006
Copy link

//是不是也要考虑下值是别的类型的情况呀;比如是数组 number 之类的

var entry = {
    'a.b.c.dd': 'abcdd',
    'a.d.xx': 'adxx',
    'a.e': 'ae',
    'f.g':["a","b"]
}
console.log(transform(entry));
function transform(entry){
  const target = {};
  const map = new Map();
  Object.keys(entry).forEach(key=>{
    map.set(entry[key],key.split('.'));
  })
  map.forEach((vs,key)=>{
    _transform(target,key);
  })
  return target;
  function _transform(parent,key){
    const k = map.get(key).shift();
    if(!map.get(key).length){
      parent[k] = key;
    }else{
      if(!parent[k]){
        parent[k] = {};
      }
      _transform(parent[k],key);
    }
  }
}

@k-0311
Copy link

k-0311 commented Jul 31, 2019

const deepTree = obj => {
    let res = {}
    for (const [key, val] of Object.entries(obj)) {
      let arr = key.split('.')
      deep(res, arr, val)
    }

    function deep(obj, arr, val) {
      let key = arr.shift()
      if(key in obj){
        deep(obj[key], arr, val)
      }else if (arr.length > 0) {
        obj[key] = {}
        deep(obj[key], arr, val)
      }else{
        obj[key] = val
      }
    }
    return res
  }

@likepeach789
Copy link

let entry = {
  'a.b.c.dd': 'abcdd',
  'a.d.xx': 'adxx',
  'a.e': 'ae',
  'b.d.e.s.e':'bdese',
  'a.v.d':'avd',
  'b.d.e.b':'bdeb'
}
let ret = {}; //保存最终结果的对象。
function convert(option) {
  for(var i in option) {
    let value = option[i];
    var keys = i.split(".")
    convertKeys(keys, ret, value);
  }
}

function convertKeys(keys, ret, value) {
  for(let i in keys) {
    let key = keys[i];
    let index = i;
     if(!ret[key]) {
        ret[key] = {};  
     } 
     if(keys.slice(index + 1).length > 0) {
          convertKeys(keys.slice(index +1), ret[key], value);
     } else { // 说明已经遍历到最后一个key, 不需要继续遍历了,直接赋值。
          ret[key] = value;
     }     
     break;
  }
}
convert(entry);
console.log(ret); //{"a":{"b":{"c":{"dd":"abcdd"}},"d":{"xx":"adxx"},"e":"ae","v":{"d":"avd"}},"b":{"d":{"e":{"s":{"e":"bdese"},"b":"bdeb"}}}}

@wabRul
Copy link

wabRul commented Sep 3, 2020

function trans(obj) {
  let res = {}
  let temp
  for (let key in obj) {
    temp = res
    let arr = key.split('.')
    let len = arr.length
    for (let i = 0; i < len - 1; i++) {
      if (!temp[arr[i]]) {
        temp[arr[i]] = {}
      }
      temp = temp[arr[i]]
    }
    temp[arr[len - 1]] = obj[key]
  }
  return res
}

@crabkiller
Copy link

crabkiller commented Sep 3, 2020

function parseToObj(obj) {
  return Object.keys(obj).reduce((res, path) => {
    const keys = path.split('.')
    const deepestObj = keys.slice(0, -1).reduce((o, key) => {
      o[key] = o[key] || {}
      return o[key]
    }, res)
    deepestObj[keys[keys.length - 1]] = obj[path]
    return res
  }, {})
}

const testObj = {
  'a.b.c.dd': 'abcdd',
  'a.d.xx': 'adxx',
  'a.e': 'ae'
}
console.log(parseToObj(testObj))

@sexyHuang
Copy link

sexyHuang commented Sep 9, 2020

const entry2normal = (input: { [key: string]: string }) => {
  const result: { [key: string]: any } = {};
  const translator = (
    [key, ...resKeys]: string[],
    value: string,
    parent = result
  ) => {
    if (!resKeys.length) {
      parent[key[0]] = value;
      return;
    }
    if (!parent[key] || typeof parent[key] === 'string') parent[key] = {};
    translator(resKeys, value, parent[key]);
  };
  Object.entries(input).forEach(([key, value]) => {
    translator(key.split('.'), value);
  });
  return result;
};

@rudyxu1102
Copy link

有点像链表

var entry = {
    'a.b.c.dd': 'abcdd',
    'a.d.xx': 'adxx',
    'a.e': 'ae'
}

const search = (keys, res, value) => {
    let cur = res
    for (let i = 0; i < keys.length; i++) {
        if (i === keys.length - 1) {
            cur[keys[i]] = value
        } else if (!cur[keys[i]]) {
            cur[keys[i]] = {}
            cur = cur[keys[i]]
        }
    }
}

const solution = (obj) => {
    let res = {}
    for (let i in obj) {
        let keys = i.split('.')
        search(keys, res, obj[i])
    }
    return res
}

console.log(solution(entry))

@huangnuoen
Copy link

function convert(entry) {
  let obj = {};
  for (const key in entry) {
    if (entry.hasOwnProperty(key)) {
      let keys = key.split(".");
// keys只有一个时直接赋值
      if (keys.length === 1) {
        obj[keys[0]] = entry[key];
        continue
      }
      if (!obj[keys[0]]) {
        obj[keys[0]] = Object.create(null);
      }
      // 储存对象最深属性的引用地址
      let temp;
      temp = obj[keys[0]];
      for (let i = 1; i < keys.length; i++) {
        if (i === keys.length - 1) {
          temp[keys[i]] = entry[key];
        } else {
          temp[keys[i]] = Object.create(null);
          temp = temp[keys[i]];
        }
      }
    }
  }
  return obj;
}

@Harhao
Copy link

Harhao commented Oct 27, 2020

function translateEntery(entry) {
    const returnValue = {}
    if(typeof entry == 'object') {
        Object.keys(entry).forEach(key => {
            if(key.includes('.')) {
                const arr = key.split('.')
                generate(returnValue, arr, entry[key])
            }
        })
    }
    function generate(returnValue, arr, value) {
        if(arr.length == 1) {
            returnValue[arr.shift()] = value
            return 
        }
        const key = arr.shift();
        !returnValue[key] && (returnValue[key] = {});
        return generate(returnValue[key], arr, value)
    }
    return returnValue
}

@mocayo
Copy link

mocayo commented Nov 5, 2020

const convert = function (obj) {
    const ans = {};

    function helper(o, prefix) {
        if (!o) {
            return;
        }

        Object.keys(o).forEach(k => {
            const v = o[k];
            const p = prefix ? `${prefix}.${k}` : k;

            switch (typeof v) {
                case 'string':
                case 'number':
                case 'boolean':
                case 'undefined':
                    ans[p] = v;
                    break;
                default:
                    helper(v, p);
                    break;
            }
        });
    }

    helper(obj, null);

    return ans;
};

var entry = {
    a: {
        b: {
            c: {
                dd: 'abcdd'
            }
        },
        d: {
            xx: 'adxx'
        },
        e: 'ae'
    }
};

console.log(convert(entry));
// {
//     'a.b.c.dd': 'abcdd',
//     'a.d.xx': 'adxx',
//     'a.e': 'ae'
// };

@negativeentropy9
Copy link

function format(entry) {
    const result = {}

    Object.keys(entry).forEach((keyDot) => {
        const keys = keyDot.split(".");
        const value = entry[keyDot];

        let tmp=result;

        while (keys.length) {
            const key = keys.shift()

            if (keys.length === 0) {
                tmp[key] = value
            } else {
                tmp[key] = tmp[key] || {}
                tmp = tmp[key];
            }
        }
    })
    
    return result
}

// 要求转换成如下对象
var entry = {
  'a.b.c.dd': 'abcdd',
  'a.d.xx': 'adxx',
  'a.e': 'ae'
};

console.log("debug-", format(entry));

@huxiaocheng
Copy link

function objTransitionStr(output) {
  const keySplit = Object.keys(output).map((key) => key.split("."));
  const values = Object.values(output);
  const res = {};
  keySplit.forEach((keys, i) => {
    keys.reduce((res, key, index) => {
      if (index === keys.length - 1) {
        res[key] = values[i];
      }
      return key in res ? res[key] : (res[key] = {});
    }, res);
  });
  return res;
}

@XW666
Copy link

XW666 commented Mar 30, 2021

var output = {
    'a.b.c.dd': 'abcdd',
    'a.d.xx': 'adxx',
    'a.e': 'ae'
  }
  const find09 = (val) => {
    let obj = {}
    for (let key in val) {
      let keys = key.split('.')
      let bb = obj
      keys.forEach((item, index) => {
        if (!bb[item]) {
              bb[item] = index !== keys.length - 1 ? {} : val[key];
              bb = bb[item]
        }
      })
    }
  }
  find09(output)

@ruanlinxin
Copy link

var entry = {
        'a.b.c.dd': 'abcdd',
        'a.d.xx': 'adxx',
        'a.e': 'ae'
    }
    function gen(data){
        const obj = {} // 创建空对象
        Object.entries(data).forEach(([keys,val])=>{
            // 获取key 和 value
            let now = obj // 保存读取到的路径
            const path = keys.split('.') // 切割keys变成路径
            const key  = path.pop() // 弹出最后一个路径用来赋值
            path.forEach(key =>{ // 遍历路径创建
                if(!(key in now)){ // 如果路径不存在那么创建一个路径
                    now[key] = {}
                }
                now = now[key] // 进入路径
            })
            now[key] = val // 给最终路径赋值
        })
        return obj
    }

    console.log(gen(entry))

@zhelingwang
Copy link

zhelingwang commented May 11, 2021

根据 x.y.z 来迭代

var entry = {
  'a.b.c.dd': 'abcdd',
  'a.d.xx': 'adxx',
  'a.e': 'ae'
}

function transformReverse(entry) {
  const output = {};
  Reflect.ownKeys(entry).forEach(key => {
    const val = entry[key];
    const keySplitByDot = key.split('.');
    let temp = output;
    while (keySplitByDot.length > 0) {
      const attr = keySplitByDot.shift();
      if (keySplitByDot.length === 0) {
        temp[attr] = val;
      } else {
        if (!temp[attr]) {
          temp[attr] = {};
        }
        temp = temp[attr];
      }
    }
  });
  console.log(output);
  return output;
}

transformReverse(entry)

@MrLeihe
Copy link

MrLeihe commented May 11, 2021

1、使用一个额外的变量 preObj 来实现

function transform(obj) {
  var res = {}
  var preObj = res
  Reflect.ownKeys(obj).forEach((key) => {
    var keys = key.split('.')
    keys.forEach((v, i) => {
      if (i === keys.length - 1) {
        // 已达最后一个键值,赋值
        preObj[v] = obj[key]
        // 重置 preObj
        preObj = res
      } else {
        // 当前 key 已存在,则取值,否则创建新对象
        preObj[v] = preObj[v] || {}
        // 改变 preObj 指向,实现链式调用
        preObj = preObj[v]
      }
    })
  })
  return res
}

2、使用 reduce 简化

function transform(obj) {
  var res = {}
  Reflect.ownKeys(obj).forEach((key) => {
    var keys = key.split('.')
    keys.reduce((pre, cur, i) => {
      if(i === keys.length - 1) {
        pre[cur] = obj[key]
      } else {
        pre[cur] = pre[cur] || {}
        pre = pre[cur]
      }
      return pre
    }, res)
  })
  return res
}
// 测试
var entry = {
  'a.b.c.dd': 'abcdd',
  'a.d.xx': 'adxx',
  'a.e': 'ae',
  k: 'k',
}

transform(entry)

image

@kvsur
Copy link

kvsur commented Jun 1, 2021

const entry = {
    'a.b.c.dd': 'abcdd',
    'a.d.xx': 'adxx',
    'a.e': 'ae',
    'a.e.f': 'cover',
    'd.x': 'dx',
    'd': 'cover-d'
};

function format(entry) {
    const result = Object.create(null);

    for (let [key, val] of Object.entries(entry)) {
        const keys = key.split('.');
        set(keys.splice(0, 1)[0], keys.reduceRight((pre, k) => ({ [k]: pre }), val), result);
    }

    return result;
}

function set(key, val, obj) {
    // 基础类型的值的话就做覆盖操作
    (typeof obj[key] !== 'object' || typeof val !== 'object') && (obj[key] = val, true)
        || Object.entries(val).forEach(([k, v]) => set(k, v, obj[key]));
}

const result = format(entry);

console.log(JSON.stringify(result))

image

@981377660LMT
Copy link

// 前缀树
const entryToTree = (entry: Dict<string>) => {
  const res = { root: {} } as Record<string, any>
  const pathes: string[][] = []

  for (const [k, v] of Object.entries(entry)) {
    pathes.push([...k.split('.'), v])
  }

  for (const path of pathes) {
    let root = res.root
    const key = path[path.length - 2]
    const value = path[path.length - 1]
    for (let i = 0; i < path.length - 2; i++) {
      const char = path[i]
      if (!Object.keys(root).includes(char)) root[char] = {}
      root = root[char]
    }
    root[key] = value
  }

  return res.root
}

@XW666
Copy link

XW666 commented Sep 9, 2021

###  const find77 = (entry) => {
    let map = {}
    for (key in entry) {
      let m = key.split('.');
      let n = map;
      m.forEach((item, index) => {
        if (!n[item]) {
          n[item] = index !== m.length - 1 ? {} : entry[key]
          n = n[item]
        }
      })
    }
  }

@j-joker
Copy link

j-joker commented Oct 12, 2021

function transform(obj) {
    let ret = {}
    function mergeObj(o1, o2) {
        Object.keys(o2).forEach(key => {
            if (key in o1) {
                o1[key] = mergeObj(o1[key], o2[key])
            } else {
                o1[key] = o2[key]
            }
        })
        return o1
    }
    Object.keys(obj).forEach(key => {
        let keyArr = key.split('.').reverse()
        let o = keyArr.reduce((pre, curKey) => {
            return {
                [curKey]: pre
            }
        }, obj[key])
        ret = mergeObj(ret, o)
    })
    console.log(ret.a.b.c)
}
var entry = {
    'a.b.c.dd': 'abcdd',
    'a.d.xx': 'adxx',
    'a.e': 'ae'
}
transform(entry)

@Rain120
Copy link

Rain120 commented Feb 17, 2022

参考: Rain120/Web-Study#18

var deFlatten = function (entry) {
    const res = {};

    var format = (res, keys, value) => {
        const key = keys.shift();

        if (!keys.length) {
            res[key] = value;
        } else {
            res[key] = res[key] || {};

            format(res[key], keys, value);
        }

    };

    for (const key in entry) {
        const keys = key.split('.');
        format(res, keys, entry[key]);
    }

    for (const key in res) {
        if (/^\w+\[\d+\]$/.test(key)) {
            const k = key.match(/^\w+/)[0];
            const i = key.match(/[\d+]/g).join('');

            res[k] = res[k] || [];
            res[k][i] = res[key];

            delete res[key];
        }
    }

    return res;
}

deFlatten({
    "a.b": 1,
    "a.c": 2,
    "asss.d.e": 5,
    "baa[0]": 1,
    "b[1]": 3,
    "b[2].a": 2,
    "b[20].b": 3,
    "c": 3
})

image

@Dylan0916
Copy link

Dylan0916 commented Apr 6, 2022

var entry2 = {
  "a.b.c.dd": "abcdd",
  "a.d.xx": "adxx",
  "a.e": "ae",
  "a.d.xy": "ae",
};

function foo(input) {
  const result = {};

  Object.entries(input).forEach(([k, v]) => {
    const keys = k.split(".");

    keys.reduce((acc, key, index) => {
      if (typeof acc[key] === "undefined") {
        acc[key] = Object.create(null);
      }

      if (index === keys.length - 1) {
        acc[key] = v;
      }

      return acc[key];
    }, result);
  });

  return result;
}

@waldonUB
Copy link

思路

  • 以"."将key分割成数组
  • 声明变量temp,利用js对象指向同一个引用地址的特性,把上一次的结果带进下一次循环中
  • length - 1为得到value的终止条件
var entry = {
  'a.b.c.dd': 'abcdd',
  'a.d.xx': 'adxx',
  'a.e': 'ae',
}
/**
 * 转换
 * @author waldon
 * @date 2022-04-11
 * @param {*} entry - param
 */
function translateEntry(entry) {
  const res = {}
  for (const key of Object.keys(entry)) {
    const keyArr = key.split('.')
    const value = entry[key]
    let temp = res
    for (let i = 0, len = keyArr.length; i < len; i++) {
      const subKey = keyArr[i]
      if (i === keyArr.length - 1) {
        temp[subKey] = value
      } else {
        temp[subKey] = temp[subKey] || {}
        temp = temp[subKey]
      }
    }
  }
  return res
}

console.log(translateEntry(entry))

@enson0131
Copy link

思路

  • 1 利用reduce写法, 将key转化为嵌套对象, 因为对象指向的是内存地址,会同步更新
  • 2 当到数组的最后一个值时,说明不再是对象,赋值即可
`
/**
 * 1 利用reduce写法, 将key转化为嵌套对象, 因为对象指向的是内存地址,会同步更新
 * 2 当到数组的最后一个值时,说明不再是对象,赋值即可
 * @param {*} obj 
 * @returns 
 */
function transform (obj) {
  const result = {};
  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
      if (key.indexOf('.') > -1) {
        const arr = key.split('.');
        arr.reduce((pre, cur, index) => {
          pre[cur] = pre[cur] || {};
          if (index === arr.length - 1) { // 赋值
            pre[cur] = obj[key];
          }
          return pre[cur];
        }, result)
      } else {
        result[key] = obj[key];
      }
    }
  }

  return result
}
`

@miniflycn
Copy link

var entry = {
    'a.b.c.dd': 'abcdd',
    'a.d.xx': 'adxx',
    'a.e': 'ae'
}

function trans(obj) {
    const res = {}
    for (let key in obj) {
        let target = res
        const path = key.split('.')
        for (let i = 0, l = path.length - 1; i < l; i++) {
            target = (target[path[i]] = target[path[i]] || {})
        }
        target[path[path.length - 1]] = obj[key]
    }
    return res
}

@wumo1016
Copy link

function test(obj) {
  const res = {}
  for (const keys in obj) {
    const keyList = keys.split('.')
    const len = keyList.length
    const loop = (target, i) => {
      const key = keyList[i]
      if (i < len - 1) {
        loop(target[key] || (target[key] = {}), i + 1)
      } else {
        target[key] = obj[keys]
      }
    }
    loop(res, 0)
  }
  return res
}

@xuhen
Copy link

xuhen commented Dec 1, 2022

function convert(obj) {
    const result = {};
    for (let k of Object.keys(obj)) {
        const paths = k.split('.');
        paths.reduce((ac, cur, idx) => {
            if (!ac[cur]) {
                if (idx === arr.length - 1) {
                    ac[cur] = obj[k];
                } else {
                    ac[cur] = {};
                }
            }
            return ac[cur];
        }, result)

    }
    return result;
}

@leonwens
Copy link

const entry = {
  'a.b.c.dd': 'abcdd',
  'a.d.xx': 'adxx',
  'a.e': 'ae'
};

function cook(obj) {
  let res = {};
  Object.keys(obj).forEach(keyPath => {
    const value = obj[keyPath];
    const list = keyPath.split('.');
    list.reduce((acc, key, index) => {
      if (index === list.length - 1) {
        acc[key] = value;
        return;
      } else {
        acc[key] = acc[key] || {};
        return acc[key];
      }
    }, res);
  });
  return res;
}

@LoveSleepMouse
Copy link

function test(obj) {
        const result = {};
        for (const key of Object.keys(obj)) {
          const list = key.split(".");
          let temp = result;
          while (list.length) {
            let keyvalue = list.shift();
            temp[keyvalue] = list.length ? temp[keyvalue] || {} : obj[key];
            temp = temp[keyvalue];
          }
        }
        return result;
      }

@gauseen
Copy link

gauseen commented Mar 24, 2023

var data = {
  'a.b.c': 'ccc',
  'a.b.d': 'ddd',
  'a.e': 'eee'
}

function solution(data) {
  var result = {}

  Object.keys(data).forEach((key) => {
    const arr = key.split('.');
    arr.reduce((acc, cur, index) => {
      acc[cur] = acc[cur] || {}
      if (index === arr.length - 1) {
        acc[cur] = data[key]
      }

      return acc[cur]
    }, result)
  })

  return result
}

console.log('solution: ', solution(data));

@Dylan0916
Copy link

function transfer(entry) {
  const result = {};

  Object.entries(entry).forEach(([string, value]) => {
    const keys = string.split('.');
    let temp = result;

    keys.forEach((key, index) => {
      if (index === keys.length - 1) {
        temp[key] = value;
      } else if (typeof temp[key] === 'undefined') {
        temp[key] = {};
      }

      temp = temp[key];
    });
  });

  return result;
}

@wendellsheh
Copy link

wendellsheh commented Apr 18, 2024

var entry = {
  'a.b.c.dd': 'abcdd',
  'a.b.c.d.e': 'abcde',
  'a.d.xx': 'adxx',
  'a.e': 'ae'
}
function convert4(entry) {
  const result = {};
  for (let key of Object.keys(entry)) {
    key.split('.').reduce((acc, cur, i, paths) => acc[cur] ??= (i === paths.length -1 ? entry[key] : {}), result)
  }
  return result;
}
console.log(convert4(entry))

@negativeentropy9
Copy link

function format(obj) {
  const result = {};

  for (let key in obj) {
    const arr = key.split(".");

    dfs(arr, result, obj[key]);
  }

  return result;

  function dfs(array, target, value) {
    if (!array.length) {
      return;
    }

    const key = array[0];

    if (array.length === 1) {
      target[key] = value;
    } else {
      const copiedArray = [...array];

      target[key] = target[key] || {};
      copiedArray.shift();
      dfs(copiedArray, target[key], value);
    }
  }
}

// output = {
//   a: {
//     b: {
//       c: {
//         dd: 'abcdd'
//       }
//     },
//     d: {
//       xx: 'adxx'
//     },
//     e: 'ae'
//    }
//  }
console.debug(
  format({
    "a.b.c.dd": "abcdd",
    "a.d.xx": "adxx",
    "a.e": "ae",
  })
);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests