鍍金池/ 問(wèn)答/HTML/ 問(wèn)一個(gè)數(shù)據(jù)結(jié)構(gòu)轉(zhuǎn)換的問(wèn)題?

問(wèn)一個(gè)數(shù)據(jù)結(jié)構(gòu)轉(zhuǎn)換的問(wèn)題?

現(xiàn)有一個(gè)數(shù)組

[
    {id: 1, pk: null, name: '學(xué)校'},
    {id: 2, pk: 1, name: '一年級(jí)'},
    {id: 3, pk: 1, name: '二年級(jí)'},
    {id: 4, pk: 1, name: '三年級(jí)'},
    {id: 6, pk: 2, name: '一班'},
    {id: 7, pk: 2, name: '二班'},
    {id: 8, pk: 2, name: '三班'},
    {id: 9, pk: 2, name: '四班'},
    {id: 10, pk: 3, name: '一班'},
    {id: 11, pk: 3, name: '二班'},
    {id: 12, pk: 3, name: '三班'},
    {id: 13, pk: 3, name: '四班'},
    {id: 14, pk: 4, name: '一班'},
    {id: 15, pk: 4, name: '二班'},
    {id: 16, pk: 4, name: '三班'},
    {id: 17, pk: 4, name: '四班'}
]

pk為null的放在最外層, 子pk對(duì)應(yīng)父id,則當(dāng)作對(duì)應(yīng)id的children, id轉(zhuǎn)為對(duì)應(yīng)的key,
id為17這一條, pk為4,則對(duì)應(yīng)為三年級(jí)的children.

最終轉(zhuǎn)換結(jié)果

[{
    title: '學(xué)校',
    key: 1,
    children: [{
        title: '一年級(jí)',
        key: 2,
        children: [{
            title: '一班',
            key: 6,
        },{
            title: '二班',
            key: 7,
        },{
            title: '三班',
            key: 8,
        },{
            title: '四班',
            key: 9,
        }]
    },{
        title: '二年級(jí)',
        key: 3,
        children: [{
            title: '一班',
            key: 10,
        },{
            title: '二班',
            key: 11,
        },{
            title: '三班',
            key: 12,
        },{
            title: '四班',
            key: 13,
        }]
    },{
        title: '三年級(jí)',
        key: 4,
        children: [{
            title: '一班',
            key: 14,
        },{
            title: '二班',
            key: 15,
        },{
            title: '三班',
            key: 16,
        },{
            title: '四班',
            key: 17,
        }]
    }]
}]

真實(shí)數(shù)據(jù)可能沒(méi)那么整齊, 但是轉(zhuǎn)換規(guī)則是這樣的, 有什么好的轉(zhuǎn)換寫(xiě)法么?

回答
編輯回答
瘋浪

無(wú)限樹(shù)結(jié)構(gòu)可以用遞歸

function buildChildren(parents, source) {
    return parents.map(parent => {
        let children = source.find(item => item.pk === parent.id);
        parent.children = buildChildren(children, source);
    });
}

let items = [ ... ];

let result = buildChildren(items.find(item=>!item.pk), items);

隨手寫(xiě)的,生產(chǎn)環(huán)境可以再優(yōu)化一下。。

2017年3月19日 05:26
編輯回答
荒城
let result = [];

let key_map = data.reduce((obj, item) => {
    return ((pk, data) => pk 
        ? (obj[pk] = obj[pk] || []).push(data) 
        : result.push(data))(item.pk, {
            title: item.name,
            key: item.id
    }), obj
}, {});

let key_walker = item => (key => key_map[key] 
    && (item.children = key_map[key]).forEach(key_walker))(item.key)

result.forEach(key_walker)

console.dir(result);

其實(shí)思路跟前邊幾位差不多,替換了一些 if 結(jié)構(gòu)而已。

2018年7月17日 12:51
編輯回答
尐懶貓
 let result = [];

  const setData = (list, d) => {
    for(let i = 0; i < list.length; i++) {
      if(list[i].key === d.pk) {
        if(!list[i].children) {
          list[i].children = [{key: d.id, title: d.name}];
        } else {
          list[i].children.push({key: d.id, title: d.name});
        }
        return list;
      } else if(list[i].children) {
        setData(list[i].children, d);
      } else {
        return list;
      }
    }
  };

  const data = [
    {id: 1, pk: null, name: '學(xué)校'},
    {id: 2, pk: 1, name: '一年級(jí)'},
    {id: 3, pk: 1, name: '二年級(jí)'},
    {id: 4, pk: 1, name: '三年級(jí)'},
    {id: 6, pk: 2, name: '一班'},
    {id: 7, pk: 2, name: '二班'},
    {id: 8, pk: 2, name: '三班'},
    {id: 9, pk: 2, name: '四班'},
    {id: 10, pk: 3, name: '一班'},
    {id: 11, pk: 3, name: '二班'},
    {id: 12, pk: 3, name: '三班'},
    {id: 13, pk: 3, name: '四班'},
    {id: 14, pk: 4, name: '一班'},
    {id: 15,pk: 4, name: '二班'},
  {id: 16, pk: 4, name: '三班'},
  {id: 17, pk: 4, name: '四班'}
  ];

  data.forEach(d => {
    if(!d.pk) {
      result.push({key: d.id, title: d.name});
    } else {
      setData(result, d);
    }
  });

  console.log(result);
2017年3月24日 09:04
編輯回答
蝶戀花
// 結(jié)果            
let result = []
// hash 用于快速查找數(shù)據(jù)
let tempList = []
arr.forEach(item => {
    // 生成待保存結(jié)構(gòu)數(shù)據(jù)
    let temp = {
        title: item.name,
        key: item.id
    }
    // 存在hash上
    tempList[item.id] = temp
    if (item.pk === null) {
        // 放置最外層
        result.push(temp)
    } else if (tempList[item.pk] !== undefined) {
        // 存在則添加至children中
        if (tempList[item.pk].children === undefined) {
            tempList[item.pk].children = []
        }
        tempList[item.pk].children.push(temp)
    } else {
        // 否則提示錯(cuò)誤
        console.log(item + '未找到對(duì)應(yīng)父級(jí)')
    }
})
2018年9月16日 07:07
編輯回答
茍活
var items = [
  {id: 1, pk: null, name: '學(xué)校'},
  {id: 2, pk: 1, name: '一年級(jí)'},
  {id: 3, pk: 1, name: '二年級(jí)'},
  {id: 4, pk: 1, name: '三年級(jí)'},
  {id: 6, pk: 2, name: '一班'},
  {id: 7, pk: 2, name: '二班'},
  {id: 8, pk: 2, name: '三班'},
  {id: 9, pk: 2, name: '四班'},
  {id: 10, pk: 3, name: '一班'},
  {id: 11, pk: 3, name: '二班'},
  {id: 12, pk: 3, name: '三班'},
  {id: 13, pk: 3, name: '四班'},
  {id: 14, pk: 4, name: '一班'},
  {id: 15,pk: 4, name: '二班'},
  {id: 16, pk: 4, name: '三班'},
  {id: 17, pk: 4, name: '四班'}
]
var ret = []
var mids = {}
items.forEach(item => {
  var data = {
    title: item.name,
    key: item.id
  }
  if (!mids[item.pk]) {
    mids[item.id] = data
    ret.push(data)
  } else {
    mids[item.id] = data
    if (!mids[item.pk].children) {
      mids[item.pk].children = []
    }
    mids[item.pk].children.push(data)
  }
})
console.log(ret)
2017年11月4日 06:24