如何添加到字典中,但过滤掉空键
本文关键字:过滤 字典 何添加 添加 | 更新日期: 2023-09-27 18:03:06
这个问题中的代码生成以下JSON:
由于.Where(a => a.Values != null)
行,代码应该排除空的"Children"键,但是它不起作用。
我在哪里可以放置Where子句,以便JSON不包括一堆空的"子"数组?
谢谢你的帮助。
[{
"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;
}
问题是您总是创建一个包含"Children"值的Dictionary,即使没有child。
解决方案是将其放入一个条件中,如果没有子元素,则不添加该值,否则无论如何都要添加带有空集合值的children Key。
下面是为我完成这个工作的代码:肉和土豆是现在在递归语句中调用的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;
}
想想这里发生了什么。你有:
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
是一堆匿名对象实例,所有这些实例都包含一个字典,其中有三个键/值对。
我认为你想要的是:
.Where(a => a["Children"] != null)
当然,假设BuildTree
对空列表返回null
。
.Where(a => a.Values != null)
中的Values
对于子代总是不为空,因为您是在递归({ "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:
.Where(a => a.Values.All(IsNotEmptyTree))