如何将点标记的命名空间字符串列表排序为嵌套的 JSON 字符串?
像这样。
var string1 = "example.string.1";
var string2 = "example.string.2";
var string3 = "example.anotherstring.1";
分类成这个。
{
"example": {
"string": ["1", "2"],
"anotherstring": ["1"]
}
}
编辑 1
谢谢大家!我能够使用您的答案让它接近工作。
使用这个列表它可以工作:
var strings = new List<string>
{
"example.string.1",
"example.string.2",
"example.anotherstring.1",
};
public void Example()
{
var dict = new Dictionary<string, dynamic>();
foreach (var s in strings)
{
AddPartsToDictionary(dict, s.Split('.'));
}
}
public void AddPartsToDictionary(IDictionary<string, dynamic> dict, string[] parts)
{
for (var i = 0; i < parts.Length; i++)
{
if (i < parts.Length - 2)
{
if (!dict.ContainsKey(parts[i]))
dict.Add(parts[i], new Dictionary<string, dynamic>());
dict = dict[parts[i]];
}
else if (i < parts.Length - 1)
{
if (!dict.ContainsKey(parts[i]))
{
var list = new List<string>();
dict[parts[i]] = list;
}
}
else
{
var list = dict[parts[i - 1]] as List<string>;
list.Add(parts[i]);
}
}
}
结果json
{
"example": {
"string": [
"1",
"2"
],
"anotherstring": [
"1"
]
}
}
这个列表失败了
var strings = new List<string>
{
"example.string.1",
"example.string.example.1",
"example.string.2",
"example.anotherstring.1",
"example.string.example.2",
"string.example.2"
};
我可能需要对列表进行排序或进行其他操作,仍在处理中。希望这有助于解决问题。
最佳答案
对象一直向下
如果一直使用对象(而不是数组)是可以的,那么这会起作用。
var strings = new List<string> {
"example.string.1",
"example.string.2",
"example.anotherstring.1",
};
var result = strings.Aggregate(new Dictionary<string, Object>(), (acc, s) =>
{
var level = acc;
foreach(var segment in s.Split('.'))
{
if (!level.ContainsKey(segment))
{
var child = new Dictionary<string, Object>();
level.Add(segment, child);
}
level = level[segment] as Dictionary<string, Object>;
}
return acc;
});
var json = JsonConvert.SerializeObject(result, Formatting.Indented);
输出一直向下都有对象。
{
"example": {
"string": {
"1": {},
"2": {}
},
"anotherstring": {
"1": {}
}
}
}
最后一级的数组 ( with a Fiddle )
如果您想要最后一级的数组,那么我们需要精确定义最后一级的定义。例如,最后一层是否总是只包含整数?如果是这样,以下工作。
var result = strings.Aggregate(new Dictionary<string, Object>(), (acc, s) =>
{
Dictionary<string, Object> previousLevel = null;
Dictionary<string, Object> nextLevel = acc;
string previousSegment = null;
foreach (string nextSegment in s.Split('.'))
{
if (Int16.TryParse(nextSegment, out _))
{
if (previousLevel[previousSegment] is Dictionary<string, Object>)
{
previousLevel[previousSegment] = new List<string>();
}
var list = previousLevel[previousSegment] as List<string>;
list.Add(nextSegment);
}
else
{
if (!nextLevel.ContainsKey(nextSegment))
{
var child = new Dictionary<string, Object>();
nextLevel.Add(nextSegment, child);
}
previousSegment = nextSegment;
previousLevel = nextLevel;
nextLevel = nextLevel[nextSegment] as Dictionary<string, Object>;
}
}
return acc;
});
输出在最后一层有数组。
{
"example": {
"string": [
"1",
"2"
],
"anotherstring": [
"1",
"2"
]
}
}
此数组版本仅在最后一级仅为 integer
类型时才有效,这正是您最初的问题所要求的。
更困难的情况是在同一级别处理混合的 string
和 integer
类型,它的输入看起来像这样:
"System.1",
"System.2",
"System.Collections.1",
"System.Collections.2",
"System.Collections.Generic.1"
这需要更复杂的算法。如果这是隐藏的要求,请考虑提出一个全新的后续问题,并在对此答案的评论中链接到它。
关于c# - 将点标记的命名空间字符串列表排序为嵌套的 JSON 字符串 c#,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49662193/