如何将点标记命名空间字符串列表排序为嵌套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"
};
我可能要对列表或其他内容进行排序,仍在继续处理。希望这有助于搞清楚。
答案 0 :(得分: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": {}
}
}
}
如果你想在最后一级使用数组,那么我们需要精确定义最后一级的定义。例如,最后一级是否只包含整数?如果是这样,以下工作。
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"
这需要更复杂的算法。如果这是隐藏的要求,请考虑提出一个全新的后续问题,并在对此答案的评论中链接到该问题。
答案 1 :(得分:1)
我认为id快速去了解它,它的关闭但不完全是你想要的。但是我认为它可能会激励你或其他人尝试。
免责声明,我不是 Json.net 爱好者,这段代码是 相当不错......不寻常,至少可以说
给出一个列表
var list = new List<string>
{
"example.string.1",
"example.string.2",
"example.anotherstring.1",
"example.anotherstring.2",
"System",
"System.Diagnostics",
"System.Text",
"System.Collections.Generic",
"System.Linq",
"System.Diagnostics.1",
"System.Text.1",
"System.Collections.Generic.1",
"System.Linq.1",
"System.Diagnostics.2",
"System.Text.2",
"System.Collections.Generic.2",
"System.Linq.2"
};
某些课程
public class RawValue
{
public RawValue(string key, IEnumerable<IEnumerable<string>> values)
{
Key = key;
Values = values;
}
public string Key { get; set; }
public IEnumerable<IEnumerable<string>> Values { get; set; }
}
public class NameSpace : Dictionary<string, NameSpace>
{
}
一些助手
private static IEnumerable<RawValue> GetRawValues(RawValue value)
{
return value.Values.Where(x => x.Any())
.GroupBy(x => x.FirstOrDefault())
.Select(x => new RawValue(x.Key, x.Select(y => y.Skip(1))));
}
private static NameSpace GroupNameSpaces(IEnumerable<RawValue> groups)
{
var result = new NameSpace();
foreach (var group in groups)
result.Add(group.Key, GroupNameSpaces(GetRawValues(group)));
return result;
}
主要代码
var groups = list.Select(x => x.Split('.'))
.GroupBy(x => x.FirstOrDefault())
.Select(x => new RawValue(x.Key, x.Select(y => y.Skip(1))));
var settings = new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore
};
var result = GroupNameSpaces(groups);
var json = JsonConvert.SerializeObject(result, Formatting.Indented, settings);
Console.WriteLine(json);
<强>输出强>
{
"example": {
"string": {
"1": {},
"2": {}
},
"anotherstring": {
"1": {},
"2": {}
}
},
"System": {
"Diagnostics": {
"1": {},
"2": {}
},
"Text": {
"1": {},
"2": {}
},
"Collections": {
"Generic": {
"1": {},
"2": {}
}
},
"Linq": {
"1": {},
"2": {}
}
}
}
由于我不知道如何在 Json.Net 中更好地进行序列化,我认为我的失败是必须使用NameSpace : Dictionary<string, NameSpace>
。也没有花时间在这上面,我无法弄清楚如何将最后一个节点转换为json数组。虽然我不确定你是否能够考虑它。但是我肯定这可以做得更好