简体   繁体   English

将对象数组转换为按值分组的数组数组

[英]Convert array of objects to array of arrays grouped by values

In the fabric.js app I have elements that are divided into several groups.在fabric.js 应用程序中,我将元素分为几组。
The user can form an arbitrary number of groups containing an arbitrary number of elements.用户可以形成包含任意数量元素的任意数量的组。
The attached image shows the elements grouped into three groups, and each element shows its ID.附加的图像显示了分为三组的元素,每个元素都显示了它的 ID。

画布元素

When the user has finished creating groups, the app measures the distance between the elements and puts the elements in a "parent - child(ren)" relation.当用户创建完组后,应用程序会测量元素之间的距离,并将元素置于“父 - 子(人)”关系中。
This results in an array of objects:这会产生一个对象数组:

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 ] }
];

Each element in a group is parent to the elements that are close to it, but at the same time it is also a child of the element closest to it.组中的每个元素都是距离它最近的元素的父元素,但同时它也是距离它最近的元素的子元素。
How, in this example, to get an array with three subarrays from the "elements" array?在此示例中,如何从“元素”数组中获取包含三个子数组的数组?
Each resulting subarray should contain ID's of elements that are only in that group.每个结果子数组应包含仅在该组中的元素的 ID。
The final result should be:最终结果应该是:

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

1) Build sets by going over elements. 1)通过遍历元素来构建集合。 For each element, check if parent is in any existing set.对于每个元素,检查 parent 是否在任何现有集合中。 If no set available then create the set.如果没有可用的集合,则创建该集合。 Add the children to the set.将孩子添加到集合中。
2) Now, we have array of sets and might have intersecting sets, which need to merge. 2)现在,我们有一组集合,并且可能有相交的集合,需要合并。
3) convert the array of sets into array of arrays. 3) 将集合数组转换为数组数组。

PS: I think step 2 of merge can be combined in step 1 itself. 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);

Here's another way to solve the problem using a stack.这是使用堆栈解决问题的另一种方法。

  • Start with a parent, traverse through it's children and their children until the stack is empty.从父母开始,遍历它的孩子和他们的孩子,直到堆栈为空。 This is one group.这是一组。
  • Maintain a visited array to avoid loops维护一个访问过的数组以避免循环
  • Push a group to the main array if it's not empty如果组不为空,则将组推送到主数组

 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));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM