我正在尝试将字符串转换为分层列表,其中字符串中的每一行代表层次结构中的单个项目。
例如说我有以下字符串:
1 - First Level 1
2 - First Level 1 > Second Level 1
3 - First Level 1 > Second Level 1 > Third Level 1
4 - First Level 1 > Second Level 2
5 - First Level 2
6 - First Level 2 > Second Level 1
7 - First Level 2 > Second Level 1 > Third Level 1
...
我需要将其转换为以下类型的列表:
public class Category {
public int Id { get; set; }
public string Name { get; set; }
public Category Parent { get; set; }
}
类别名称不能包含 - 或>字符。
E.g。以下一行:
3 - 第一级1>第二级1>第三级
将一个类别添加到列表中,其id为3,名称为“Third Level 1”,Parent将指向名称为“Second Level 1”的类别(在上面的示例中id = 2,不是id = 6)。
请注意,可能有多个具有相同名称的类别,因此需要查找整个路径以获取父级。
到目前为止,我已经设法将每行的字符串拆分,然后对于每一行我对连字符进行另一次拆分以获取id和完整的类别名称。然后我可以对大于符号进行进一步拆分以检索类别部分。我拿最后一部分来获取类别名称,如果有多个部分,我知道我需要查找父类。
这是我迷失的地方,因为我现在需要使用其余的部分来计算父母,考虑到上面的多个类别可能具有相同的名称
如果有人能告诉我这是怎么做的,我会很感激。感谢
答案 0 :(得分:2)
如果我正确理解了您的问题陈述,则此代码应该有效
var strings = File.ReadAllLines(@"C:\YourDirectory\categories.txt");
var categories = new List<Category>();
foreach (var line in strings)
{
var category = new Category(); //line = 3 - First Level 1 -> Second Level 1 -> Third Level 1
var cats = line.Split('>').ToList(); //3 - First Level 1, Second Level 1, Third Level 1
category.Id = int.Parse(cats.First().Split('-').First().Trim()); //3
if (cats.Count > 1)
{
category.Name = cats.Last().Trim(); //Third Level 1
var parentStr = cats.ElementAt(cats.Count - 2).Trim();
if (parentStr.Contains('-'))
parentStr = parentStr.Split('-').Last().Trim();
category.Parent = categories.FirstOrDefault(c => c.Name == parentStr);
}
else
category.Name = cats.First().Split('-').Last().Trim(); //for 1 - First Level 1
categories.Add(category);
}
<强>更新强>
澄清之后,这是更改后的代码
var lines = File.ReadAllLines(@"C:\YourDirectory\categories.txt");
var lookup = new List<KeyValuePair<List<string>, Category>>(); //key = parents in order
foreach (var line in lines)
{
var category = new Category (); //line = 3 - First Level 1 -> Second Level 1 -> Third Level 1
var parts = line.Split('>').ToList(); //3 - First Level 1, Second Level 1, Third Level 1
category.Id = int.Parse(parts.First().Split('-').First().Trim()); //3
if (parts.Count > 1) //has parent
{
category.Name = parts.Last().Trim(); //Third Level 1
if (parts.Count == 2) //has one level parent
{
var parentStr = parts.First().Split('-').Last().Trim();
if (lookup.Any(l => l.Value.Parent == null && l.Value.Name == parentStr))
{
var parent = lookup.First(l => l.Value.Parent == null && l.Value.Name == parentStr);
category.Parent = parent.Value;
lookup.Add(new KeyValuePair<List<string>,Category>(new List<string> { parent.Value.Name }, category));
}
}
else //has multi level parent
{
var higherAncestors = parts.Take(parts.Count - 2).Select(a => a.Split('-').Last().Trim()).ToList(); //.GetRange(1, parts.Count - 2).Select(a => a.Trim()).ToList();
var parentStr = parts.Skip(parts.Count - 2).First().Trim();
if (lookup.Any(l => MatchAncestors(l.Key, higherAncestors) && l.Value.Name == parentStr))
{
var parent = lookup.First(l => MatchAncestors(l.Key, higherAncestors) && l.Value.Name == parentStr);
category.Parent = parent.Value;
var ancestors = parent.Key.ToList();
ancestors.Add(parent.Value.Name);
lookup.Add(new KeyValuePair<List<string>, Category>(ancestors, category));
}
}
}
else //no parent
{
category.Name = parts.First().Split('-').Last().Trim(); //for 1 - First Level 1
lookup.Add(new KeyValuePair<List<string>,Category> (new List<string>(), category));
}
}
var categories = lookup.Select(l => l.Value); //THIS IS YOUR RESULT
private static bool MatchAncestors(List<string> ancestors1, List<string> ancestors2)
{
if (ancestors1.Count != ancestors2.Count)
return false;
for (int i = 0; i < ancestors1.Count; i++)
{
if (ancestors1[i] != ancestors2[i])
return false;
}
return true;
}
对于此测试数据:
1 - First Level 1
2 - First Level 1 > Second Level 1
3 - First Level 1 > Second Level 1 > Third Level 1
4 - First Level 1 > Second Level 2
5 - First Level 2
6 - First Level 2 > Second Level 1
7 - First Level 2 > Second Level 1 > Third Level 1
8 - First Level 2 > Second Level 1 > Third Level 1 > Fourth Level 1
9 - First Level 1 > Second Level 1 > Third Level 1 > Fourth Level 2
这是查找值(如json):
[
{
"Key": [],
"Value": {
"Id": 1,
"Name": "First Level 1",
"Parent": null
}
},
{
"Key": ["First Level 1"],
"Value": {
"Id": 2,
"Name": "Second Level 1",
"Parent": {
"Id": 1,
"Name": "First Level 1",
"Parent": null
}
}
},
{
"Key": ["First Level 1","Second Level 1"],
"Value": {
"Id": 3,
"Name": "Third Level 1",
"Parent": {
"Id": 2,
"Name": "Second Level 1",
"Parent": {
"Id": 1,
"Name": "First Level 1",
"Parent": null
}
}
}
},
{
"Key": ["First Level 1"],
"Value": {
"Id": 4,
"Name": "Second Level 2",
"Parent": {
"Id": 1,
"Name": "First Level 1",
"Parent": null
}
}
},
{
"Key": [],
"Value": {
"Id": 5,
"Name": "First Level 2",
"Parent": null
}
},
{
"Key": ["First Level 2"],
"Value": {
"Id": 6,
"Name": "Second Level 1",
"Parent": {
"Id": 5,
"Name": "First Level 2",
"Parent": null
}
}
},
{
"Key": ["First Level 2","Second Level 1"],
"Value": {
"Id": 7,
"Name": "Third Level 1",
"Parent": {
"Id": 6,
"Name": "Second Level 1",
"Parent": {
"Id": 5,
"Name": "First Level 2",
"Parent": null
}
}
}
},
{
"Key": ["First Level 2","Second Level 1","Third Level 1"],
"Value": {
"Id": 8,
"Name": "Fourth Level 1",
"Parent": {
"Id": 7,
"Name": "Third Level 1",
"Parent": {
"Id": 6,
"Name": "Second Level 1",
"Parent": {
"Id": 5,
"Name": "First Level 2",
"Parent": null
}
}
}
}
},
{
"Key": ["First Level 1","Second Level 1","Third Level 1"],
"Value": {
"Id": 9,
"Name": "Fourth Level 2",
"Parent": {
"Id": 3,
"Name": "Third Level 1",
"Parent": {
"Id": 2,
"Name": "Second Level 1",
"Parent": {
"Id": 1,
"Name": "First Level 1",
"Parent": null
}
}
}
}
}
]
答案 1 :(得分:2)
因为我更喜欢它,我让你的课堂不可变:
searchResult
通过使用此代码,我得到了所有可用类别的平面列表,其中每个类别都获得对其父级的引用:
public class Category
{
public int Id { get; private set; }
public string Name { get; private set; }
public Category Parent { get; private set; }
public Category(int id, string name, Category parent)
{
Id = id;
Name = name;
Parent = parent;
}
public override string ToString()
{
return Id + " " + Name
+ (Parent == null ? String.Empty : (Environment.NewLine + " Parent: " + Parent));
}
}
仅用于可视化调用:
var categories = new Dictionary<String, Category>(StringComparer.InvariantCultureIgnoreCase);
using (var reader = new StringReader(_SampleData))
{
string line;
while ((line = reader.ReadLine()) != null)
{
if (String.IsNullOrWhiteSpace(line))
continue;
var elements = line.Split('-');
var id = int.Parse(elements[0]);
var name = elements[1].Trim();
var index = name.LastIndexOf('>');
Category parent = null;
if (index >= 0)
{
var parentName = name.Substring(0, index).Trim();
categories.TryGetValue(parentName, out parent);
}
var category = new Category(id, name, parent);
categories.Add(category.Name, category);
}
}
输出结果为:
foreach (var item in categories.Values)
{
Console.WriteLine(item);
}