JS題目之陣列資料拆分重組轉成巢狀物件,讓腦細胞活躍下

CRPER發表於2019-01-17

前言

下班的時候在群裡看到一個小夥伴,在群裡問了一道js的題,發現沒人理會他;

來了興趣就折騰了下,以下是解答過程,用的是ES6+的特性,在chrome跑的;

有興趣的小夥伴可以瞧瞧~~謝謝


題目

JS題目之陣列資料拆分重組轉成巢狀物件,讓腦細胞活躍下

效果圖

JS題目之陣列資料拆分重組轉成巢狀物件,讓腦細胞活躍下


解答

儘量註釋,我分步驟解答

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)
複製程式碼

總結

這個只是其中的一個解決姿勢,肯定還有其他更優的法子;

僅供參考,不對之處請留言,會及時修正...

相關文章