2

この質問のコードは、次のJSONを生成します。

コードは、行のおかげで空の「子」キーを除外する必要があります.Where(a => a.Values != null)が、機能しません。

JSONに空の「Children」配列が含まれないように、where句をどこに配置できますか?

ご協力いただきありがとうございます。

[{
        "NodeID" : 1,
        "NodeText" : "Country",
        "Children" : [{
                "NodeID" : 3,
                "NodeText" : "President",
                "Children" : []
            }, {
                "NodeID" : 4,
                "NodeText" : "Population",
                "Children" : []
            }, {
                "NodeID" : 5,
                "NodeText" : "State",
                "Children" : [{
                        "NodeID" : 6,
                        "NodeText" : "Governor",
                        "Children" : []
                    }, {
                        "NodeID" : 7,
                        "NodeText" : "Population",
                        "Children" : []
                    }, {
                        "NodeID" : 8,
                        "NodeText" : "County",
                        "Children" : [{
                                "NodeID" : 9,
                                "NodeText" : "Population",
                                "Children" : []
                            }
                        ]
                    }
                ]
            }
        ]
    }, {
        "NodeID" : 2,
        "NodeText" : "Year",
        "Children" : []
    }
]

上記のJSONを生成するサンプルコードは次のとおりです。

public class Node
{
    public int? ParentNodeID { get; set; }
    public int NodeID { get; set; }
    public string NodeText { get; set; }

    public Node(int? parentNodeID, int nodeID, string nodeText)
    {
        ParentNodeID = parentNodeID;
        NodeID = nodeID;
        NodeText = nodeText;
    }
}

public List<Dictionary<string, object>> BuildTree(int? parentNodeID = null, List<Node> exampleData = null)
{
    // kickstart the recursion with example data
    if (exampleData == null)
    {
        exampleData = new List<Node>();
        exampleData.Add(new Node(null, 1, "Country"));
        exampleData.Add(new Node(null, 2, "Year"));
        exampleData.Add(new Node(1, 3, "President"));
        exampleData.Add(new Node(1, 4, "Population"));
        exampleData.Add(new Node(1, 5, "State"));
        exampleData.Add(new Node(5, 6, "Governor"));
        exampleData.Add(new Node(5, 7, "Population"));
        exampleData.Add(new Node(5, 8, "County"));
        exampleData.Add(new Node(8, 9, "Population"));
    }

    List<Dictionary<string, object>> result = new List<Dictionary<string, object>>();

    var nodes = exampleData.Where(a => a.ParentNodeID == parentNodeID).ToList();

    if (nodes != null)
    {
        result.AddRange(nodes
            .Select(a => new Dictionary<string, object> {
                { "NodeID", a.NodeID},
                { "NodeText", a.NodeText },
                { "Children", BuildTree(a.NodeID, exampleData) }
            })
            .Where(a => a.Values != null) // this doesn't have any effect
            .ToList()
        );
    }
    return result;
}
4

3 に答える 3

2

問題は、子がない場合でも、常に「Children」の値を含む辞書を作成していることです。

解決策は、それを条件に入れ、子がない場合は値を追加しないことです。それ以外の場合は、何があっても空のコレクション値で子キーを追加し続けます。

これを達成するために私が働いているコードは次のとおりです。肉とジャガイモはFunc<T> getNodeDictionary、再帰ステートメント内で呼び出されるようになりました。

    public static List<Dictionary<string, object>> BuildTree(int? parentNodeID = null, List<Node> exampleData = null)
    {
        // kickstart the recursion with example data
        if (exampleData == null)
        {
            exampleData = new List<Node>();
            exampleData.Add(new Node(null, 1, "Country"));
            exampleData.Add(new Node(null, 2, "Year"));
            exampleData.Add(new Node(1, 3, "President"));
            exampleData.Add(new Node(1, 4, "Population"));
            exampleData.Add(new Node(1, 5, "State"));
            exampleData.Add(new Node(5, 6, "Governor"));
            exampleData.Add(new Node(5, 7, "Population"));
            exampleData.Add(new Node(5, 8, "County"));
            exampleData.Add(new Node(8, 9, "Population"));
        }

        List<Dictionary<string, object>> result = new List<Dictionary<string, object>>();

        var nodes = exampleData.Where(a => a.ParentNodeID == parentNodeID).ToList();

        if (nodes != null)
        {
            Func<Node, Dictionary<string, object>> getNodeDictionary = n => {
                var children = BuildTree(n.NodeID, exampleData); // still recursive
                var returnDictionary = new Dictionary<string, object> { // these 2 nodes always get added
                    { "NodeID", n.NodeID},
                    { "NodeText", n.NodeText }
                };

                // This ensures we only add Children if there are actually any children
                if (children.Any())
                {
                    returnDictionary.Add("Children", children);
                }

                return returnDictionary;
            };

            // No need for where clause since we now do not add the empty elements
            result.AddRange(nodes
                .Select(a => getNodeDictionary(a))
                .ToList()
            );
        }

        return result;
    }
于 2013-03-08T20:40:51.737 に答える
0

ここで何が起こっているか考えてみてください。あなたが持っている:

result.AddRange(nodes
    .Select(a => new Dictionary<string, object> {
        { "NodeID", a.NodeID},
        { "NodeText", a.NodeText },
        { "Children", BuildTree(a.NodeID, exampleData) }
    })
    .Where(a => a.Values != null) // this doesn't have any effect
    .ToList()
);

Where、ノードではなく、作成した新しいアイテムをチェックしています。だからそれは言うようなものです:

var temp1 = nodes.Select(a => new Dictionary<string, object> { ... });
var temp2 = temp1.Where(a => a.Values != null);
result.AddRange(temp2);

これらの匿名オブジェクトインスタンスの束temp1も同様です。これらのインスタンスにはすべて、3つのキーと値のペアを持つディクショナリが含まれています。

私はあなたが欲しいものは次のとおりだと思います:

.Where(a => a["Children"] != null)

もちろん、それが空のリストにBuildTree戻ると仮定します。null

于 2013-03-08T20:19:33.693 に答える
0

Valuesin.Where(a => a.Values != null)は、再帰で初期化するため、子の場合は常にnullではありません({ "Children", BuildTree(a.NodeID, exampleData) })。Where条件を変更して、空の子をチェックします。

メソッドを追加できます:

    private static bool IsNotEmptyTree(object value)
    {
        if (value == null) return false;  //Is empty whatever
        if (value as List<Dictionary<string, object>> != null)
        {
            var dict = (value as List<Dictionary<string, object>>);
            return dict.Count > 0;
        }
        // not empty
        return true;
    }

そしてそれをどこで使用するか:

.Where(a => a.Values.All(IsNotEmptyTree))
于 2013-03-08T19:49:58.610 に答える