简体   繁体   English

在C#中将共享相同父项和子项的项目分组

[英]Group the items sharing the same parent and child in C#

I wish to find an efficient way to group the items in a tree graph which has the following characteristics: 我希望找到一种在树状图中对项目进行分组的有效方法,它具有以下特征:

About the tree graph, it has multiple layers like this, if drawn horizontally: 关于树图,如果水平绘制,它具有多个这样的层:

(0,0)--(1,0)--(2,0)
   \ \-(1,1)--(2,1)
    \--(1,2)--/
  1. For a node (x,y) modeled by a class Node, x is its "level" while y is its "index". 对于由类Node建模的节点(x,y),x是其“级别”,而y是其“索引”。 For any edge we only allow sequential indexes for the two nodes of this edge, so (1,2)-(3,2) is forbidden. 对于任何边缘,我们仅允许该边缘的两个节点的顺序索引,因此(1,2)-(3,2)被禁止。
  2. Allow multiple roots: (0,0) (0,1) ...etc. 允许多个根:(0,0)(0,1)...等

About "group the items": Because in the data source of the tree there are nodes like: 关于“对项目进行分组”:因为在树的数据源中有类似以下的节点:

(3,5)--(4,10)--(5,5)
  \  \-(4,11)-/  /
   \    ....    /
    \--(4,80)--/

I wish to group the nodes like those (4,10~80) above into one node, which these nodes share the same characteristics 我希望将上面的那些节点(4,10〜80)分组为一个节点,这些节点具有相同的特征

  1. has only 1 parent node which they share 他们只有1个父节点
  2. has only 1 child node which they share 他们只有1个子节点
  3. Also need to tackle the case which they only have a common parent (or a common child) but have no children (or parents) at all. 还需要解决这样的情况,即他们只有一个共同的父母(或一个共同的孩子),却根本没有孩子(或父母)。

using a special class CompoundNode, a subclass of Node. 使用特殊的类CompositeNode,它是Node的子类。

Here is a skeleton class for Node: 这是Node的骨架类:

public class Node
{
    public Node(string id)
    {
        Id = id;
    }

    public string Id { get; set; }

    private readonly List<Node> children = new List<Node>();
    public List<Node> Children { get { return children; } }
    private readonly List<Node> parents = new List<Node>();
    public List<Node> Parents { get { return parents; } }

    protected bool Equals(Node other)
    {
        ....
    }

    public override bool Equals(object obj)
    {
        ....
    }

    public override int GetHashCode()
    {
        return (Id != null ? Id.GetHashCode() : 0);
    }

    public override string ToString()
    {
        ....
    }
}

Thanks! 谢谢!

EDIT: 编辑:

Here is the solution i did (extracts the relationship without modifying the tree), without tackling the situation of zero parent or zero child: 这是我所做的解决方案(无需修改树即可提取关系),而无需解决零父零子的情况:

        var relationships = new List<Tuple<string, string, string>>();

        foreach (var middle in nodes)
        {
            if (middle.Children.Count == 1 && middle.Parents.Count == 1)
            {
                var child = middle.Children[0];
                var parent = middle.Parents[0];
                relationships.Add(new Tuple<string, string, string>(parent.Id, middle.Id, child.Id));
            }
        }
        var groups = relationships.GroupBy(t => new { t.Item1, t.Item3 }).Where(a => a.Count() > 1);

        var toGroupedRelations = groups.Cast<IEnumerable<Tuple<string, string, string>>>().ToList();

Ok - here's a first attempt. 好的-这是第一次尝试。 Should give you some good pointers anyway: 无论如何应该给你一些很好的指示:

var nodes = new List<Node>();

// !! populate your nodes list with all your real nodes first!

// filter to nodes with at most 1 parent and 1 child
// group by a tuple containing the parent (if it exists) and the child (if it exists)
var grouped = nodes.Where(i => i.Children.Count <= 1 && i.Parents.Count <= 1)
    .GroupBy(i => 
        new Tuple<Node, Node>(i.Parents.Count == 0 ? null : i.Parents[0], 
                                i.Children.Count == 0 ? null : i.Children[0]));

// go through your groups - each one should be a cluster of nodes to be merged
foreach (var group in grouped)
{
    // get the first node in the group (which one is arbitrary if we're merging anyway)
    var node = group.First();

    // if this group has a parent
    if (node.Parents.Count == 1)
    {
        // change the parent to only have one child - this one!
        node.Parents[0].Children.Clear();
        node.Parents[0].Children.Add(node);
    }

    // if this group has a child
    if (node.Children.Count == 1)
    {
        // change the child to only have one parent - this one!
        node.Children[0].Parents.Clear();
        node.Children[0].Parents.Add(node);
    }
}

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

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