3

我正在寻找从平面列表到层次结构的数据转换。我怎样才能以一种可读的方式实现这一点,但在性能上仍然可以接受,是否有任何我可以利用的 .NET 库。我认为这在某些术语中被认为是“方面”(在这种情况下是行业)。

public class Company
{        
    public int CompanyId { get; set; }
    public string CompanyName { get; set; }
    public Industry Industry { get; set; }
}

public class Industry
{
    public int IndustryId { get; set; }
    public string IndustryName { get; set; }
    public int? ParentIndustryId { get; set; }
    public Industry ParentIndustry { get; set; }
    public ICollection<Industry> ChildIndustries { get; set; }
}

现在假设我有一个List<Company>并且我正在寻找将它转换为List<IndustryNode>

//Hierarchical data structure
public class IndustryNode
{
    public string IndustryName{ get; set; }
    public double Hits { get; set; }
    public IndustryNode[] ChildIndustryNodes{ get; set; }
}

这样生成的对象在序列化后应该如下所示:

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

其中“Hits”是属于该组的公司数量。

为了澄清,我需要将 aList<Company>转换为List<IndustryNode> NOT 序列化 aList<IndustryNode>

4

4 回答 4

1

尝试这个:

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

未经测试

于 2013-10-15T15:30:36.037 回答
0

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

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

于 2013-10-15T15:31:43.673 回答
0

尝试为此目的使用 json 序列化程序。我看你的数据结构没问题,这只是序列化的问题。

var industryNodeInstance = LoadIndustryNodeInstance();

var json = new JavaScriptSerializer().Serialize(industryNodeInstance);

如果您想在序列化程序之间进行选择,请参阅: http ://www.servicestack.net/benchmarks/#burningmonk-benchmarks

LoadIndustryNodeInstance 方法

  • 建造List<Industry>

  • 兑换IndustryTree = List<IndustryNode>

  • 实现 Tree 方法,例如 Traverse。尝试查看 C# 中的 Tree 数据结构

于 2013-10-15T15:44:34.043 回答
0

这里有一些伪代码可能会让你一路走好。我创建了一个地图/字典索引并用公司列表填充它。然后我们从索引中提取顶级节点。请注意,可能存在边缘情况(例如,该索引最初可能需要部分填充,因为您的任何公司似乎都没有引用最顶层节点,因此必须以其他方式填充这些节点) .

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);
于 2013-10-15T16:04:01.493 回答