代码之家  ›  专栏  ›  技术社区  ›  Olli Savolainen

从节点集创建组

  •  0
  • Olli Savolainen  · 技术社区  · 16 年前

    sets[
     a[1,2,5,6],
     b[1,4,5],
     c[1,2,5],
     d[2,5],
     e[1,6],
    ]
    

    我想生成一个新的结构,一个组列表,每个组都有

    • 对这些节点所属的原始集的引用

    因此,上述数据将变得(组的顺序无关)。

    group1{nodes[2,5],sets[a,c,e]}
    group2{nodes[1,2,5],sets[a,c]}
    group3{nodes[1,6],sets[a,e]}
    group4{nodes[1,5],sets[a,b,c]}
    

    我假设我可以将数据作为数组/对象结构输入并处理它,然后以所需的任何格式输出结果结构。

    如果:

    • 所有组至少有2个节点和2组。
    • 当节点子集包含在形成组的较大集合中时,则只有较大的集合才能获得组:在本例中,节点1,2没有自己的组,因为它们共同拥有的所有集合都已出现在组2中。

    (这些集合存储在XML中,到目前为止,我也成功地将其转换为JSON,但这与此无关。我可以理解过程(伪)代码,但XSLT或Scala中的框架之类的东西可能有助于入门。)

    2 回复  |  直到 16 年前
        1
  •  1
  •   Beta    16 年前
    1. 浏览一下集合列表。每套
      1. 浏览小组列表。每组G
        1. 如果S可以是G的成员(即,如果G的集合是S的子集),则将S添加到G。
        2. 如果S不能成为G的成员,但S和G集合的交集包含多个节点,则为该交集创建一个新组并将其添加到列表中。
      2. 给S一个自己的组并将其添加到列表中。
    2. 删除只有一个成员集的任何组。

    [1,2,5,6] [a]
    [1,5] [a,b]
    [1,4,5] [b]
    

    读了c之后,它是

    [1,2,5,6] [a]
    [1,5] [a,b,c]
    [1,4,5] [b]
    [1,2,5] [a,c]
    

    如果速度是个问题的话,还有稍微更有效的算法。

        2
  •  0
  •   Olli Savolainen    16 年前
    /*
    Pseudocode algorithm for creating groups data from a set dataset, further explained in the project documentation. This is based on 
    http://stackoverflow.com/questions/1644387/create-groups-from-sets-of-nodes
    
    I am assuming 
    - Group is a structure (class) the objects of which contain two lists: a list of sets and a list of nodes (group.nodes). Its constructor accepts a list of nodes and a reference to a Set object
    - Set is a list structure (class), the objects (set)  of which contain the nodes of the list in set.nodes
    - groups and sets are both list structures that can contain arbitrary objects which can be iterated with foreach(). 
    - you can get the objects two lists have in common as a new list with intersection()
    - you can count the number of objects in a list with length()
    */
    
    //Create groups, going through the original sets
    foreach(sets as set){
        if(groups.nodes.length==0){
            groups.addGroup(new Group(set.nodes, set));
        }
        else{
            foreach (groups as group){
                    if(group.nodes.length() == intersection(group.nodes,set.nodes).length()){
                        // the group is a subset of the set, so just add the set as a member the group
                        group.addset(set);
                        if (group.nodes.length() < set.nodes.length()){
                        // if the set has more nodes than the group that already exists, 
                        // create a new group for the nodes of the set, with set as a member of that group
                        groups.addGroup(new Group(set.nodes, set));
                        }
                    }
    
                    // If group is not a subset of set, and the intersection of the nodes of the group 
                    // and the nodes of the set
                    // is greater than one (they have more than one person in common), create a new group with 
                    // those nodes they have in common, with set as a member of that group
                    else if(group.nodes.length() > intersection(group.nodes,set.nodes).length() 
                        && intersection(group.nodes,set.nodes).length()>1){
                        groups.addGroup(new Group(intersection(group.nodes,set.nodes), set);
                    }
            }
        }
    
    }
    
    // Cleanup time!
    foreach(groups as group){
        //delete any group with only one member set (for it is not really a group then)
        if (group.sets.length<2){
            groups.remove(group);
        }
        // combine any groups that have the same set of nodes. Is this really needed? 
        foreach(groups2 as group2){
            //if the size of the intersection of the groups is the same size as either of the 
            //groups, then the groups have the same nodes.
            if (intersection(group.nodes,group2.nodes).length == group.nodes.length){
                foreach(group2.sets as set2){
                    if(!group.hasset(set)){
                        group.addset(set2);
                    }
                }
                groups.remove(group2);
            }
            }
    
    }