1

MasterproductID = 1以下のコードから、フィルタリングして、その下にある子のみを取得したいと考えています。フィルタリングすることによりMasterproductID = 2MasterproductID = 3. その方法を教えてください。ご協力いただきありがとうございます。

class TreeNode
{
    public int MasterProductId;
    public int? ParentId;
}

protected void Page_Load(object sender, EventArgs e)
{
    var list = new List<TreeNode>{

        new TreeNode{ MasterProductId = 1 },
        new TreeNode{ MasterProductId = 4, ParentId = 1 },
        new TreeNode{ MasterProductId = 7, ParentId= 4 },
        new TreeNode{ MasterProductId = 5, ParentId = 1 },
        new TreeNode{ MasterProductId = 6, ParentId = 1 },

        new TreeNode{ MasterProductId = 2 },
        new TreeNode{ MasterProductId = 7, ParentId = 2 },
        new TreeNode{ MasterProductId = 8, ParentId= 7 },

        new TreeNode{ MasterProductId = 3 },

    };

    foreach (var item in Level(list, null, 0))
    {
        if (item.Value == 0)
        {
            Response.Write(String.Format("<b>MasterProductId={0}, Level={1}", item.Key, item.Value) + "</b><br />");
        }
        else
        {
            Response.Write(String.Format("MasterProductId={0}, Level={1}", item.Key, item.Value) + "<br />");
        }
    }
}

private static IEnumerable<KeyValuePair<int, int>> Level(List<TreeNode> list, int? parentId, int lvl)
{
    return list
        .Where(x => x.ParentId == parentId)
        .SelectMany(x =>
            new[] { new KeyValuePair<int, int>(x.MasterProductId, lvl) }.Concat(Level(list, x.MasterProductId, lvl + 1))
        );
}
4

2 に答える 2

1

メソッドはすでに、Levelほぼ正確に目的を果たしています。foreachが 1の を指定するように変更された場合ParentId:

foreach (var item in Level(list, 1, 0))

次に、ノード 4、7、8、5、および 6 の出力を生成します。つまり、ノードの子孫を返します。

指定した親ノードも含めたい場合は、それを結果のリストに連結するだけで済みます。例えば:

private static IEnumerable<KeyValuePair<int, int>> LevelIncl(
                 List<TreeNode> list, int parentId)
{
    return new[] {new KeyValuePair<int, int>(parentId, 0)}
              .Concat(Level(list, parentId, 1));
}

その後:

foreach (var item in LevelIncl(list, 1))

これにより、ノード 1、4、7、8、5、および 6 の出力が生成されます。

于 2012-11-23T17:10:14.467 に答える
0

サンプルコードや説明から明らかではない、単純にこれを使用できない理由はありますか?

.Where(x => x.MasterProductId == 1 || (x.ParentId.HasValue && x.ParentId.Value == 1))

示唆されているように、親の関係だけでなく、再帰的な祖先の関係を探している場合、データ構造を更新すると、目標が非常に容易になります。

class TreeNode
{
    public int MasterProductId;
    public int? ParentId;

    private TreeNode parent; 
        // How this gets set requires other data structures, and some knowledge of
        // how you are loading the data--but this should give you the outline of an idea

    public bool HasAncestor(int referenceId, int ancestor) {

        if (!parentId.HasValue) 
        { 
            return false 
        };

        if (parentId.Value == ancestor) 
        {
            return true;
        }

        return parent.HasAncestor(ancestor);                
    }
}

その後、次のことができます。

 .Where(x => x.MasterProductId == 1 || x.HasAncestor(1))

親を実装する最善の方法は、残りの実装の詳細attributeに依存します。既知のすべてのノードを追跡するコンテナ クラスにカプセル化します。そのマップは、親参照を設定するために の構築に使用されます。TreeNodeMap<int, TreeNode>TreeNode

于 2012-11-23T16:47:17.727 に答える