C# 将平面阵列数据转换为层次结构

C# 将平面阵列数据转换为层次结构,c#,.net,data-structures,C#,.net,Data Structures,我希望将数据从平面列表转换为层次结构。如何以可读的方式实现这一点,但性能仍然可以接受?是否有任何.NET库可以利用。我认为这在某些术语中被认为是一个“方面”(在本例中是由行业定义的) 因此,序列化后的结果对象应如下所示: { IndustryName: "Industry", ChildIndustryNodes: [ { IndustryName: "Energy", ChildIndustryNodes: [

我希望将数据从平面列表转换为层次结构。如何以可读的方式实现这一点,但性能仍然可以接受?是否有任何.NET库可以利用。我认为这在某些术语中被认为是一个“方面”(在本例中是由行业定义的)

因此,序列化后的结果对象应如下所示:

{
    IndustryName: "Industry",
    ChildIndustryNodes: [
        {
            IndustryName: "Energy",
            ChildIndustryNodes: [
                {
                    IndustryName: "Energy Equipment & Services",
                    ChildIndustryNodes: [
                        { IndustryName: "Oil & Gas Drilling", Hits: 8 },
                        { IndustryName: "Oil & Gas Equipment & Services", Hits: 4 }
                    ]
                },
                {
                    IndustryName: "Oil & Gas",
                    ChildIndustryNodes: [
                        { IndustryName: "Integrated Oil & Gas", Hits: 13 },
                        { IndustryName: "Oil & Gas Exploration & Production", Hits: 5 },
                        { IndustryName: "Oil & Gas Refining & Marketing & Transporation", Hits: 22 }
                    ]
                }
            ]
        },
        {
            IndustryName: "Materials",
            ChildIndustryNodes: [
                {
                    IndustryName: "Chemicals",
                    ChildIndustryNodes: [
                        { IndustryName: "Commodity Chemicals", Hits: 24 },
                        { IndustryName: "Diversified Chemicals", Hits: 66 },
                        { IndustryName: "Fertilizers & Agricultural Chemicals", Hits: 22 },
                        { IndustryName: "Industrial Gases", Hits: 11 },
                        { IndustryName: "Specialty Chemicals", Hits: 43 }
                    ]
                }
            ]
        }
    ]
}
其中“点击率”是属于该组的公司数量

为了澄清,我需要将
列表
转换为
列表
而不是序列化
列表

尝试以下方法:

    private static IEnumerable<Industry> GetAllIndustries(Industry ind)
    {
        yield return ind;
        foreach (var item in ind.ChildIndustries)
        {
            foreach (var inner in GetAllIndustries(item))
            {
                yield return inner;
            }
        }
    }

    private static IndustryNode[] GetChildIndustries(Industry i)
    {
        return i.ChildIndustries.Select(ii => new IndustryNode()
        {
            IndustryName = ii.IndustryName,
            Hits = counts[ii],
            ChildIndustryNodes = GetChildIndustries(ii)
        }).ToArray();
    }


    private static Dictionary<Industry, int> counts;
    static void Main(string[] args)
    {
        List<Company> companies = new List<Company>();
        //...
        var allIndustries = companies.SelectMany(c => GetAllIndustries(c.Industry)).ToList();
        HashSet<Industry> distinctInd = new HashSet<Industry>(allIndustries);
        counts = distinctInd.ToDictionary(e => e, e => allIndustries.Count(i => i == e));
        var listTop = distinctInd.Where(i => i.ParentIndustry == null)
                        .Select(i =>  new IndustryNode()
                                {
                                    ChildIndustryNodes = GetChildIndustries(i),
                                    Hits = counts[i],
                                    IndustryName = i.IndustryName
                                }
                        );
    }
私有静态IEnumerable GetAllIndustries(行业索引)
{
收益率指数;
foreach(工业中的var项目)
{
foreach(GetAllIndustries内部var(项目))
{
内部收益率;
}
}
}
私有静态行业代码[]GetChildIndustries(行业一)
{
return i.ChildIndustries.Select(ii=>newindustrynode()
{
行业名称=ii.行业名称,
点击次数=计数[ii],
ChildIndustryNodes=GetChildIndustries(二)
}).ToArray();
}
私有静态字典计数;
静态void Main(字符串[]参数)
{
上市公司=新上市公司();
//...
var allIndustries=companys.SelectMany(c=>GetAllIndustries(c.Industry)).ToList();
HashSet-Differentind=新的HashSet(所有行业);
counts=distincond.ToDictionary(e=>e,e=>allIndustries.Count(i=>i==e));
var listTop=distincend.Where(i=>i.ParentIndustry==null)
.Select(i=>newindustrynode()
{
ChildIndustryNodes=GetChildIndustries(i),
点击次数=计数[i],
行业名称
}
);
}

未经测试

您正在寻找序列化程序。MSFT有一个是VS的原生版本,但我喜欢免费的Newtonsofts。MSFT文档和示例是,Newtonsoft文档是


Newtonsoft是免费的、简单的、快速的。

尝试使用json序列化程序来实现这一目的。我看你的数据结构还可以,这只是序列化的问题

var industryNodeInstance = LoadIndustryNodeInstance();

var json = new JavaScriptSerializer().Serialize(industryNodeInstance);
如果要在序列化程序之间进行选择,请参见以下内容:

LoadIndustryNodeInstance方法

  • 生成
    列表

  • 转换
    IndustryTree=List

  • 实现树方法,例如遍历。试着看


    • 以下是一些psuedo代码,可能会帮助您顺利完成任务。我创建了一个地图/字典索引,并用公司列表填充它。然后我们从索引中提取顶级节点。请注意,可能存在边缘情况(例如,最初可能需要部分填充此索引,因为您的任何公司似乎都没有引用顶级节点,因此必须以其他方式填充这些节点)

      字典索引=新字典();
      公开作废插入(公司)
      { 
      if(索引ContainsKey(公司、行业、行业名称))
      {
      索引[公司.行业.行业名称].hits++;
      }
      其他的
      {
      IndustryNode节点=新的IndustryNode(IndustryName=company.Industry,Hits=1);
      索引[node.IndustryName]=节点;
      if(index.ContainsKey(company.Industry.ParentIndustry.IndustryName))
      {
      索引[company.Industry.ParentIndustry.IndustryName].ChildrenIndustries.Add(节点);
      }
      }    
      }
      列表topLevelNodes=索引
      .Where(kvp=>kvp.Item.ParentIndustry==null)
      .ToList(kvp=>kvp.Item);
      
      效率是什么意思?最具可读性和可维护性,还是性能最好?对不起,我没有说清楚。它需要有效率,但我愿意在可读性和可维护性之间做一些折衷,即使它最终会序列化。为什么需要性能?你的名单似乎很小。我真的不喜欢有人无缘无故地给我一个负号。如果你没有理由,不要投反对票。我没有投反对票,但答案没有帮助。我已经在使用JSON.NET进行序列化了,但我仍然需要将其放入正确的结构中。这在最初的帖子中并不清楚(正如一半的答案所证明的)。听起来你好像在找表演。对不起,我误解了你的问题。我仍然认为不解释原因就减去一是很糟糕的。问题是
      LoadIndustryNodeInstance()
      中发生了什么。我有一个
      列表
      而不是
      列表
      如果某个行业的子公司不受公司影响,此解决方案将不考虑该行业的子公司。@AhmedKRAIEM True,这些必须先插入。感谢您的回答,如果这种方法取而代之的是一个行业,那么在哪里可以应用递归来处理儿童之子的问题呢?你能进一步解释吗?按照当前数据的呈现方式,递归不能立即使用。例如,您可以通过递归搜索树,但这与线性搜索没有什么不同,因为没有指定的搜索顺序。
      distrinctInd.Where(i=>i.ParentIndustry==null)
      不匹配任何元素,因为公司从未引用任何顶级行业元素。我一直试图让它以其他方式工作,但仍然有很多困难。请尝试
      distincend.Where(I=>I.ChildIndustries==null | | I.ChildIndustries.Count==0)
          private static IEnumerable<Industry> GetAllIndustries(Industry ind)
          {
              yield return ind;
              foreach (var item in ind.ChildIndustries)
              {
                  foreach (var inner in GetAllIndustries(item))
                  {
                      yield return inner;
                  }
              }
          }
      
          private static IndustryNode[] GetChildIndustries(Industry i)
          {
              return i.ChildIndustries.Select(ii => new IndustryNode()
              {
                  IndustryName = ii.IndustryName,
                  Hits = counts[ii],
                  ChildIndustryNodes = GetChildIndustries(ii)
              }).ToArray();
          }
      
      
          private static Dictionary<Industry, int> counts;
          static void Main(string[] args)
          {
              List<Company> companies = new List<Company>();
              //...
              var allIndustries = companies.SelectMany(c => GetAllIndustries(c.Industry)).ToList();
              HashSet<Industry> distinctInd = new HashSet<Industry>(allIndustries);
              counts = distinctInd.ToDictionary(e => e, e => allIndustries.Count(i => i == e));
              var listTop = distinctInd.Where(i => i.ParentIndustry == null)
                              .Select(i =>  new IndustryNode()
                                      {
                                          ChildIndustryNodes = GetChildIndustries(i),
                                          Hits = counts[i],
                                          IndustryName = i.IndustryName
                                      }
                              );
          }
      
      var industryNodeInstance = LoadIndustryNodeInstance();
      
      var json = new JavaScriptSerializer().Serialize(industryNodeInstance);
      
      Dictionary<String, IndustryNode> index = new Dictionary<String, IndustryNode>();
      
      public void insert(Company company)
      { 
          if(index.ContainsKey(company.Industry.IndustryName))
          {
              index[company.Industry.IndustryName].hits++;
          }
          else
          {
              IndustryNode node = new IndustryNode(IndustryName=company.Industry, Hits=1);
              index[node.IndustryName] = node;
              if(index.ContainsKey(company.Industry.ParentIndustry.IndustryName))
              {
                  index[company.Industry.ParentIndustry.IndustryName].ChildrenIndustries.Add(node);
              }
          }    
      }
      
      List<IndustryNode> topLevelNodes = index
          .Where(kvp => kvp.Item.ParentIndustry == null)
          .ToList(kvp => kvp.Item);