解析需要时间

时间:2018-04-15 08:47:13

标签: c# asp.net-mvc list parsing object

我在c#中有一个类对象列表。类具有以下属性:

int id;
int parentId;

id 是当前对象的id,parentId是parent的id。

现在我在列表中有超过100个对象。 我想解析这些对象并以格式(如树结构)生成结果

第一名 - 第二名 - 第三名 - 第四名

其中每个都是级别

例如:如果我们有8个对象{1,0},{2,1},{3,1},{4,3},{5,3},{6,2},{7, 1},{8,4} 结果应该是:

第一名 - 第二名 - 第三名 - 第四名

1 - - -

1 2 - -

1 2 6 -

1 3 - -

1 3 5 -

1 3 4 -

1 3 4 8

1 7 - -

目前我正在做的是使用4 for loops as,

@for(var item in Model ){
    for(var second in Model ){
         if(second.parentId == item.id){
                //add to table
         }
         for(var third in Model ){
               if(third .parentId == item.id){
                //add to table
               }
               for(var fourth in Model ){

                      if(fourth .parentId == item.id){
                            //add to table
                       }
               }
          }
    }

}

这里的事情可以正常工作,但由于我在列表中有100多个对象(n ^ 4的复杂性),因此需要花费太多时间来解析。

有没有其他方法可以达到同样的目的?

1 个答案:

答案 0 :(得分:1)

有必要以允许有效访问父ID的子ID的方式排列数据。这可以通过扫描输入列表并将结果存储到从parentID映射到子ID列表的字典中以恒定时间完成。方便的是,Linq提供了.ToLookup扩展方法,它几乎可以做到这一点,并且大概是O(N)的成本。

可以提供根节点,也可以在恒定时间内扫描根节点。 (实际上可能有不止一个。就此而言,数据可能包含循环)。

然后递归地遍历树,如果没有循环,可以在O(N)时间内完成。

示例代码:

using System;
using System.Linq;
using System.Collections.Generic;

public class Program
{
    class Link
    {
        public int id;
        public int parentId;
    }


    static List<Link> GetInput()
    {
        var data = new Dictionary<int, int> {{1,0},{2,1},{3,1},{4,3},{5,3},{6,2},{7,1},{8,4}};
        return data.Select(pair => new Link { id = pair.Key, parentId = pair.Value }).ToList();     
    }

    public static void Main()
    {
        List<Link> inputData = GetInput();

        // Scan the nodes and arrange as a lookup (dictionary that maps from parentId to child ids)
        ILookup<int, int> nodes = inputData.ToLookup( link => link.parentId, link => link.id );

        // Find root node(s)
        // (ints that appear as parent IDs, but as child id)
        IEnumerable<int> roots = inputData
            .Select( link => link.parentId)
            .Except( inputData.Select( link => link.id ) );

        foreach (int rootId in roots)
        {
            Display(rootId, nodes, "", 3);
        }       
    }

    static void Display(int id, ILookup<int, int> nodes, string prefix, int padding)
    {
        // Write node to console
        Console.Write(prefix);
        Console.Write(id);
        for (int i=0; i<padding; i++)
        {
            Console.Write(" --");
        }
        Console.WriteLine();

        // Recursively write children to console
        string newPrefix = prefix + id.ToString() + " ";
        foreach (int childId in nodes[id])
        {
            Display( childId, nodes, newPrefix, padding-1 );        
        }
    }   
}

可能有很多事情可以改进,但它会完成这项工作。