递归复制而不覆盖

时间:2018-02-01 13:18:02

标签: javascript arrays recursion merge ecmascript-6

我的数据如下:

`+---------------+-------+
| groups_field | value |
+---------------+-------+
| 1-1           |     2 |
| 1-2-1         |     4 |
| 2-1           |     3 |
| 2-2-4         |     8 |
+---------------+-------+`

我希望这些数据成为一个多维对象数组,如下所示:

`groups: [{
   id: 1,
   fields: [{
      id: 1,
      value: 2
   }], 
   groups: [{
      id: 2, 
      fields: [{
         id: 1,
         value: 4
       }]
   }]
 },
 {
    id: 2,
    fields: [{
       id: 1,
       value: 3
    }],
    groups: [{
       id: 2,
       fields: [{
          id: 4,
          value: 8
       }]
     }]
}]`

我已经想出如何使用reduceRight获得大部分内容:

let gfArray = row.groups_field.split('-')
let newRow = gfArray.reduceRight((obj, key, index) => {
  var a = {}
  if (index === gfArray.length - 1) {
    a = {id: key, value: row.value}
  } else if (index === gfArray.length - 2) {
    a.fields = [obj]
    a.id = key
  } else if (index === 0) {
    a.groups = obj
    a.id = key
  } else {
    a.id = key
    a.groups = [obj]
  }
  return a
}, {})
product_data.push(newRow)

给了我这个:

`groups: [{
   id: 1,
   fields: [{
      id: 1,
      value: 2
   }]
 },
{
   id: 1,
   groups: [{
      id: 2, 
      fields: [{
         id: 1,
         value: 4
       }]
   }]
 },
 {
    id: 2,
    fields: [{
       id: 1,
       value: 3
    }]
 },
 {
    id: 2,
    groups: [{
       id: 2,
       fields: [{
          id: 4,
          value: 8
       }]
     }]
 }]`

因此有一种方法可以递归地合并这些对象,因为组的数量是动态的,因此一个级别具有组或字段,它不会被覆盖,但是" push"进入阵列?或者是否有更简单的方法将我的字符串列表和字段转换为多维对象数组。

我还需要为每个级别添加一个名称prop,对于每个组和字段,我可以在使用另一个递归函数后执行此操作...我认为。

仅供参考,我在Vuejs中使用这个,所以es6 js可用。

1 个答案:

答案 0 :(得分:0)

我认为您的原始数据是:

 const rows = [{
   groups_field: "1-1",
   value: 2
 },
 // ...
];

所以现在我们需要一个可以附加数据的根对象和一个嵌套的哈希表来加快搜索速度:

 const root = { groups: [], fields: [] };
 const hash = { _:root };

现在让我们回顾一下条目:

for(const {groups_field, value} of rows){

要获取字段,我们需要拆分组字段:

 const groups = groups_field.split("-");
 const field = groups.pop();

现在是黑魔法:我们沿着嵌套的哈希表移动并创建尚不存在的树路径:

 let path = hash;
 for(const id of groups){
  // If the entry does not exist in the hashtable yet:
  if(!path[id]){
   // Create a new entry
   const el = {
     id,
     groups:[],
     fields: []
   };
   // Add a new path to the nested hashtable containing the new entry as an exit
   path[id] = { _: el };
   // Add the entry to the groups
   path._.groups.push(el);
 }
 // Go dow one level in the hashtable:
 path = path[id];
}

现在最后我们只需要添加字段:

path._.fields.push({ id: field, fields: value });

现在root包含了所需的结果......

注意:_是哈希表出口节点标识符。使用Symbol绝对会更优雅,但为了清晰起见,我将其留下了。