C# 搜索类的层次结构并返回到达该层次结构的路径
我有这个类,一个类别的层次结构C# 搜索类的层次结构并返回到达该层次结构的路径,c#,C#,我有这个类,一个类别的层次结构 class Categories { public long Id { get; set; } public long ParentId { get; set; } public string Name { get; set; } public bool IsActive { get; set; } public List<Categories> ChildrenData { get; set; } }
class Categories
{
public long Id { get; set; }
public long ParentId { get; set; }
public string Name { get; set; }
public bool IsActive { get; set; }
public List<Categories> ChildrenData { get; set; }
}
如何递归地遍历这个未知深度的类并返回到达该类的路径
所有Id值都是唯一的。假设我想找到Id=23,并通过连接Name获得到达该位置的路径
例如,在下图中,搜索ID=23将返回:默认类别/书籍/非小说类/畅销书
示例层次结构
我提供了两种方法,第一种是递归的,最后一种不是 以递归方式,添加对父对象的引用。通过这种方式,当您找到匹配项时,您可以轻松地沿链向上遍历以创建路径
class Categories
{
public Categories Parent { get; set; }
public long Id { get; set; }
public long ParentId { get; set; }
public string Name { get; set; }
public bool IsActive { get; set; }
public List<Categories> ChildrenData { get; set; }
}
现在,如果递归不是您想要的,那么将当前路径传递给Find方法
用法:
var nonRecusive = cats.Find(23, null);
我提供了两种方法,第一种是递归的,最后一种不是 以递归方式,添加对父对象的引用。通过这种方式,当您找到匹配项时,您可以轻松地沿链向上遍历以创建路径
class Categories
{
public Categories Parent { get; set; }
public long Id { get; set; }
public long ParentId { get; set; }
public string Name { get; set; }
public bool IsActive { get; set; }
public List<Categories> ChildrenData { get; set; }
}
现在,如果递归不是您想要的,那么将当前路径传递给Find方法
用法:
var nonRecusive = cats.Find(23, null);
我的建议是首先建立一个索引:
public static Dictionary<long, Category> IndexBuilder(Category c)
{
var index = new Dictionary<long, Category>();
IndexBuilder(c, index);
return index;
}
private static void IndexBuilder(Category c, Dictionary<long, Category> index)
{
if (index.ContainsKey(c.Id))
return;
index[c.Id] = c;
foreach(var child in c.ChildrenData)
IndexBuilder(child, index);
}
现在您有了一个查找,您的路径很容易生成:
static IEnumerable<Category> PathToRoot(long id, Dictionary<long, Category> index)
{
// Presumably the parent id of the top category is a sentinel.
long current = id
while (current != 0)
{
var category = index[current];
yield return category;
current = category.ParentId;
}
}
或者我们只是继续,直到索引用完:
static IEnumerable<Category> PathToRoot(long id, Dictionary<long, Category> index)
{
long current = id
while (index.ContainsKey(current))
{
var category = index[current];
yield return category;
current = category.ParentId;
}
}
现在您有了一个工具,可以用来制作字符串:
static string Slash<T>(this IEnumerable<T> items) =>
string.Join("/", items);
var s = PathToRoot(23, index)
.Reverse()
.Select(c => c.Name)
.Slash();
看到我在这里干什么了吗?制作一组助手方法,每个方法大约有五行长,可以组合在一起形成强大的解决方案。我的建议是,首先建立一个索引:
public static Dictionary<long, Category> IndexBuilder(Category c)
{
var index = new Dictionary<long, Category>();
IndexBuilder(c, index);
return index;
}
private static void IndexBuilder(Category c, Dictionary<long, Category> index)
{
if (index.ContainsKey(c.Id))
return;
index[c.Id] = c;
foreach(var child in c.ChildrenData)
IndexBuilder(child, index);
}
现在您有了一个查找,您的路径很容易生成:
static IEnumerable<Category> PathToRoot(long id, Dictionary<long, Category> index)
{
// Presumably the parent id of the top category is a sentinel.
long current = id
while (current != 0)
{
var category = index[current];
yield return category;
current = category.ParentId;
}
}
或者我们只是继续,直到索引用完:
static IEnumerable<Category> PathToRoot(long id, Dictionary<long, Category> index)
{
long current = id
while (index.ContainsKey(current))
{
var category = index[current];
yield return category;
current = category.ParentId;
}
}
现在您有了一个工具,可以用来制作字符串:
static string Slash<T>(this IEnumerable<T> items) =>
string.Join("/", items);
var s = PathToRoot(23, index)
.Reverse()
.Select(c => c.Name)
.Slash();
看到我在这里干什么了吗?制作一组助手方法,每个方法大约有五行长,可以组合在一起形成强大的解决方案。这将获得您使用递归所需要的:
void Main()
{
var data = GetData();
Console.WriteLine(GetPath(data, 23, ""));
}
public String GetPath(Categories c, Int32 id, String path)
{
if (c.Id == id)
{
return path + "/" + c.Name;
}
foreach (var cd in c.ChildrenData)
{
var p = GetPath(cd, id, path + "/" + c.Name);
if (!String.IsNullOrWhiteSpace(p))
{
return p;
}
}
return "";
}
public class Categories
{
public long Id { get; set; }
public long ParentId { get; set; }
public string Name { get; set; }
public bool IsActive { get; set; }
public List<Categories> ChildrenData { get; set; }
}
public Categories GetData()
{
return
new Categories
{
Id = 1,
Name = "Default Category",
ChildrenData = new List<Categories>
{
new Categories
{
Id = 2,
Name = "Magazines",
ChildrenData = new List<Categories> {}
},
new Categories
{
Id = 2,
Name = "Books",
ChildrenData = new List<Categories>
{
new Categories
{
Id = 20,
Name = "Fiction",
ChildrenData = new List<Categories> {}
},
new Categories
{
Id = 21,
Name = "Nonfiction",
ChildrenData = new List<Categories>
{
new Categories
{
Id = 22,
Name = "New",
ChildrenData = new List<Categories> {}
},
new Categories
{
Id = 23,
Name = "Best-Sellers",
ChildrenData = new List<Categories> {}
},
}
}
}
}
}
};
}
这将使用递归得到您想要的结果:
void Main()
{
var data = GetData();
Console.WriteLine(GetPath(data, 23, ""));
}
public String GetPath(Categories c, Int32 id, String path)
{
if (c.Id == id)
{
return path + "/" + c.Name;
}
foreach (var cd in c.ChildrenData)
{
var p = GetPath(cd, id, path + "/" + c.Name);
if (!String.IsNullOrWhiteSpace(p))
{
return p;
}
}
return "";
}
public class Categories
{
public long Id { get; set; }
public long ParentId { get; set; }
public string Name { get; set; }
public bool IsActive { get; set; }
public List<Categories> ChildrenData { get; set; }
}
public Categories GetData()
{
return
new Categories
{
Id = 1,
Name = "Default Category",
ChildrenData = new List<Categories>
{
new Categories
{
Id = 2,
Name = "Magazines",
ChildrenData = new List<Categories> {}
},
new Categories
{
Id = 2,
Name = "Books",
ChildrenData = new List<Categories>
{
new Categories
{
Id = 20,
Name = "Fiction",
ChildrenData = new List<Categories> {}
},
new Categories
{
Id = 21,
Name = "Nonfiction",
ChildrenData = new List<Categories>
{
new Categories
{
Id = 22,
Name = "New",
ChildrenData = new List<Categories> {}
},
new Categories
{
Id = 23,
Name = "Best-Sellers",
ChildrenData = new List<Categories> {}
},
}
}
}
}
}
};
}
你对c语言中的递归函数了解多少?另外,请注意,类名最好是单数分类,而不是复数。Magento标记有什么原因吗?这似乎是一个C问题,与PHP无关…@gunr217它不必是递归的,我想这可能是唯一的解决方案。这是一个针对来自magento2的json响应的示例,不确定标记是否应该在这里您是否有一个接受Id并返回类别的方法?如果你有,那么问题就变得非常简单。如果你不知道,那就有点难了。你对c语言中的递归函数了解多少?另外,请注意,类名最好是单数分类,而不是复数。Magento标记有什么原因吗?这似乎是一个C问题,与PHP无关…@gunr217它不必是递归的,我想这可能是唯一的解决方案。这是一个针对来自magento2的json响应的示例,不确定标记是否应该在这里您是否有一个接受Id并返回类别的方法?如果你有,那么问题就变得非常简单。如果你不这样做,那就更难了。