【问题标题】:Convert array of objects to array of arrays grouped by values将对象数组转换为按值分组的数组数组
【发布时间】:2020-06-15 09:20:12
【问题描述】:

在 fabric.js 应用程序中,我将元素分为几组。
用户可以形成包含任意数量元素的任意数量的组。
附图显示了分成三组的元素,每个元素都显示了它的 ID。

当用户创建完组后,应用程序会测量元素之间的距离并将元素置于“父-子(ren)”关系中。
这会产生一个对象数组:

var elements = [
    { "parent": 1, "children": [ 2 ] },
    { "parent": 2, "children": [ 1 ] },
    { "parent": 3, "children": [ 7 ] },
    { "parent": 4, "children": [ 5, 6 ] },
    { "parent": 5, "children": [ 4, 6, 7 ] },
    { "parent": 6, "children": [ 4, 5 ] },
    { "parent": 7, "children": [ 3, 5 ] },
    { "parent": 8, "children": [ 9 ] },
    { "parent": 9, "children": [ 8, 11 ] },
    { "parent": 10, "children": [ 11, 12 ] },
    { "parent": 11, "children": [ 9, 10 ] },
    { "parent": 12, "children": [ 10 ] }
];

组中的每个元素都是靠近它的元素的父元素,但同时它也是最靠近它的元素的子元素。
在此示例中,如何从“元素”数组中获取包含三个子数组的数组?
每个结果子数组都应包含仅在该组中的元素的 ID。
最终结果应该是:

var groups = [
    [1, 2],
    [3, 4, 5, 6, 7],
    [8, 9, 10, 11, 12]
];

【问题讨论】:

    标签: javascript arrays fabricjs


    【解决方案1】:

    1) 通过遍历元素来构建集合。对于每个元素,检查 parent 是否在任何现有集合中。如果没有可用的集合,则创建集合。将孩子添加到集合中。
    2)现在,我们有一组集合,并且可能有需要合并的相交集合。
    3) 将集合数组转换为数组数组。

    PS:我认为合并的第 2 步可以合并到第 1 步中。

    var elements = [
      { parent: 1, children: [2] },
      { parent: 2, children: [1] },
      { parent: 3, children: [7] },
      { parent: 4, children: [5, 6] },
      { parent: 5, children: [4, 6, 7] },
      { parent: 6, children: [4, 5] },
      { parent: 7, children: [3, 5] },
      { parent: 8, children: [9] },
      { parent: 9, children: [8, 11] },
      { parent: 10, children: [11, 12] },
      { parent: 11, children: [9, 10] },
      { parent: 12, children: [10] }
    ];
    
    const arrSets = [];
    
    elements.forEach(({ parent, children }) => {
      let set = arrSets.find(set => set.has(parent));
      if (!set) {
        set = new Set();
        set.add(parent);
        arrSets.push(set);
      }
      children.forEach(x => set.add(x));
    });
    
    const resSets = [];
    arrSets.forEach(set => {
      let curr = resSets.find(dat => [...set].some(x => dat.has(x)));
      if (!curr) {
        curr = new Set();
        resSets.push(curr);
      }
      [...set].forEach(x => curr.add(x));
    });
    
    const arr = resSets.map(set => [...set]);
    
    console.log(arr);

    【讨论】:

      【解决方案2】:

      这是使用堆栈解决问题的另一种方法。

      • 从父级开始,遍历其子级及其子级,直到堆栈为空。这是一组。
      • 维护访问过的数组以避免循环
      • 如果组不为空,则将组推送到主数组

      function findGrops(elements) {
        const eleMap = {};
        // build a parent => children map
        elements.forEach( e => {
          eleMap[e.parent] = e.children;
        });
      
        const groups = [];
        const visited = {};
      
        // iterate in a depth first way
        // parent -> children -> their children until empty
        Object.keys(eleMap).forEach( k => {
          let grp = [];
          let stk = [k]; //parseInt(k,10) to avoid the quotes
          while( stk.length > 0) {
            let x = stk.pop();
            if (!(x in visited)) {
              grp.push(x);
              visited[x] = true;
              // add children to the stack
              stk = stk.concat(eleMap[x]);
            }
          }
          // push to groups array
          grp.length && groups.push(grp);
        });
      
        return groups;
      }
      
      const input = [
          { "parent": 1, "children": [ 2 ] },
          { "parent": 2, "children": [ 1 ] },
          { "parent": 3, "children": [ 7 ] },
          { "parent": 4, "children": [ 5, 6 ] },
          { "parent": 5, "children": [ 4, 6, 7 ] },
          { "parent": 6, "children": [ 4, 5 ] },
          { "parent": 7, "children": [ 3, 5 ] },
          { "parent": 8, "children": [ 9 ] },
          { "parent": 9, "children": [ 8, 11 ] },
          { "parent": 10, "children": [ 11, 12 ] },
          { "parent": 11, "children": [ 9, 10 ] },
          { "parent": 12, "children": [ 10 ] }
      ];
      
        console.log('result:', findGrops(input));

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-07-29
        • 1970-01-01
        • 2019-06-05
        • 1970-01-01
        • 2020-05-14
        • 2018-10-13
        相关资源
        最近更新 更多