5

私はこの問題に数日間立ち往生しており、いくつかのアイデアをいただければ幸いです。オブジェクトのコレクションがあります

 public class Hierarchy
{
    public Hierarchy(string iD, string name, int level, string parentID, string topParent)
    {
        ID = iD;
        Name = name;
        Level = level;
        ParentID = parentID;
        Children = new HashSet<Hierarchy>();
    }
    public string ID { get; set; }
    public string Name{ get; set; }
    public int Level { get; set; }
    public string ParentID { get; set; }
    public ICollection<Hierarchy> Children { get; set; }
}

Linqクエリからエンティティへのデータは次のとおりです。

ID      Name     Level ParentID
295152  name1    1     null
12345   child1   2     295152
54321   child2   2     295152
44444   child1a  3     12345
33333   child1b  3     12345
22222   child2a  3     54321
22221   child2b  3     54321
22002   child2c  3     54321
20001   child2a2 4     22222
20101   child2b2 4     22222

このデータは、未知のレベルの深さまで拡張される可能性があります(私は4つだけを示しています)。最終的には、複数の子オブジェクトのコレクションを持つ1つの階層オブジェクトがあり、複数の子オブジェクトのコレクションを持つ可能性があります...など...常にトップレベルのオブジェクトは1つだけです。

このプロジェクトでは、可能な限りLinqを使用しようとしています。

これには明らかにある種の再帰的な方法が必要ですが、私は立ち往生しています。任意のアイデアや助けをいただければ幸いです。

TIA

4

2 に答える 2

4

実際、反復的な解決策はおそらくはるかに簡単です。手順は次のとおりです。

  1. IDに基づいてすべてのノードを辞書にハッシュします
  2. もう一度ループして、各ノードをその親の子リストに追加します

そのように見えます:

Hierarchy CreateTree(IEnumerable<Hierarchy> Nodes)
{
    var idToNode = Nodes.ToDictionary(n => n.ID, n => n);

    Hierarchy root;
    foreach (var n in Nodes)
    {
        if (n.ID == null)
        {
            if (root != null)
            {
                //there are multiple roots in the data
            }
            root = n;
            continue;
        }

        Hierarchy parent;
        if (!idToNode.TryGetValue(n.ID, parent))
        {
            //Parent doesn't exist, orphaned entry
        }

        parent.Children.Add(n);
    }

    if (root == null)
    {
        //There was no root element
    }
    return root;
}

データ形式には、明らかなエラー状態がいくつかあります。それらをどうするかはあなた次第です。

一般に、反復解と再帰解が常にあります。特定の問題はどちらが簡単かを変えます。

于 2013-01-11T04:52:25.527 に答える
4

この再帰関数を試すことができます:

void PopulateChildren(Hierarchy root, ICollection<Hierarchy> source)
{
    foreach (var hierarchy in source.Where(h => h.ParentID == root.ParentID))
    {
        root.Children.Add(hierarchy);
        PopulateChildren(root, source);
    }
}

あなたはこのように使うことができます:

ICollection<Hierarchy> hierarchies = new List<Hierarchy>(); // source

// Get root
var root = hierarchies.Single(h => h.Level == 1);

// Populate children recursively
PopulateChildren(root, hierarchies);
于 2013-01-11T07:38:19.360 に答える