前言
下班的时候在群里看到一个小伙伴,在群里问了一道js
的题,发现没人理会他;
来了兴趣就折腾了下,以下是解答过程,用的是ES6+
的特性,在chrome跑的
;
有兴趣的小伙伴可以瞧瞧~~谢谢
题目
效果图
解答
尽量注释,我分步骤解答
1:数组变形
格式:先拿到数据格式如下;
[ [ 'code', 'Zh' ], [ 'code', 'Cn' ], [ 'taobao', '.cn' ], [ 'taobao', '.com' ] ]
实现
这一步是拆开数据拿到我们想要的,比如基于大写字母,基于域名后缀;
因为数据格式是死的,所以正则也相对较为简单
let arr = ['codeZh', 'codeCn', 'taobao.cn', 'taobao.com']; let arrSplit = arr.map(item => { if (item.indexOf('.')!== -1){ return item.replace(/(\.)/g, ",$1").split(',') } else { return item.replace(/([A-Z])+/g, ",$1").split(',') } }) console.log(arrSplit);
2:输出构建对象数据
格式:先拿到数据格式如下;
[ { code: { Zh: 'codeZh' } }, { code: { Cn: 'codeCn' } }, { taobao: { '.cn': 'taobao.cn' } }, { taobao: { '.com': 'taobao.com' } } ]
实现
let arrGroup = arrSplit.map(item => { return {[item[0]]:{[item[1]]:item.join('')}} }) console.log(arrGroup);
3: 实现符合的JSON
格式 : 先拿到数据格式如下;
{ "code": { "Zh": "codeZh", "Cn": "codeCn" }, "taobao": { ".cn": "taobao.cn", ".com": "taobao.com" } }
实现
let resultObj = {}; for (let i = 0; i < arrGroup.length; i++){ for (const [key, value] of Object.entries(arrGroup[i])) { resultObj[key] = { ...resultObj[key], ...value } } } console.log(resultObj);
完整代码
// 求数组转换成jso //['codeZh', 'codeCn', 'taobao.cn', 'taobao.com'] // 输出 /* { 'code':{Zh:'codeZh',Cn:'codeCn'}, 'taobao':{'.cn':'taobao.cn},'.com':'taobao.com' } */ const resultObj = {}; let arr = ['codeZh', 'codeCn', 'taobao.cn', 'taobao.com']; let arrSplit = arr.map(item => (item.indexOf('.') !== -1 ? item.replace(/(\.)/g, ",$1").split(',') : item.replace(/([A-Z])+/g, ",$1").split(','))) let arrGroup = arrSplit.map(item => ({ [item[0]]: { [item[1]]: item.join('') } })) for (let i = 0; i < arrGroup.length; i++){ for (const [key, value] of Object.entries(arrGroup[i])) { resultObj[key] = { ...resultObj[key], ...value } } } console.log(arrSplit); console.log(arrGroup); console.log(resultObj);
更优雅的姿势,来自评论
- 来自掘友Der: 正向预查询结合
reduce
组合对象;
代码的思路
reducer 主要接受两个参数,callback(回调函数)和initialValue(初始值)
回调函数接收4个参数:(累加器,当前值,当前索引,数组)
看懂reduce之后就好理解了,传入空对象作为初始值,正向预查捕获大写字母或小数点,
然后以这个为基准点进行切割字符串为数组,提取到两个变量里面
依次构建题目所需的格式了,至于最终会输出一个题目答案的对象,累加器的作用.
传入值是对象,所以针对遍历处理的行为都是处理同一个对象
const list = ['codeZh', 'codeCn', 'taobao.cn', 'taobao.com'] const result = list.reduce((map, item) => { const [head, tail] = item.split(/(?=[A-Z]|\.)/) map[head] = map[head] || {} map[head][tail] = item return map }, {}) console.log(result)
- 来自掘友老姚
代码的思路
这个是
replace
的高级用法,replace
可以传入正则捕获,回调函数包括如下(match,$1,$2)
,还有偏移量和字符串检测内部的交换机制和组合与上个法子的差不多
const result = {} const list = ['codeZh', 'codeCn', 'taobao.cn', 'taobao.com'] list.join().replace(/([a-z]+)([A-Z\.][a-z]+)/g, (m, c0, c1) => { result[c0] = result[c0] || {} result[c0][c1] = m }) console.log(result)