我有一个List<Category>
,其中Category
是:
public class Category {
public List<Category> Categories { get; set; } // this holds sub-categories
public string Name { get; set; }
public string Icon { get; set; }
public string Id { get; set; }
}
由于Categories
本身是另一个List<Category>
,因此它可以包含子类别,而这些子类别可以包含子类别,等等......
我知道我可以查询第一个“图层”,如下所示:
Categories.Where(x => x.Categories.Any(c => c.Id == id)).FirstOrDefault();
如何在对象树中有效地查询特定Category
Id
,可能是3,4或5层(最多有3个,但为了将来参考我会想知道吗?
修改
此外,如果我只有3层深的子类别Category
,我如何获得整个对象树,一直到顶级Id
?
答案 0 :(得分:1)
您可以编写如下所示的扩展方法,将Category
展平为IEnumerable<Category>
:
public static IEnumerable<Category> Flatten(this Category category)
{
if (category.Categories != null)
{
foreach (var sub in category.Categories)
{
foreach (var subSub in sub.Flatten())
yield return subSub;
}
}
yield return category;
}
然后根据需要在IEnumerable<Category>
上使用Linq:
var filtered = categoryList.SelectMany(x => x.Flatten())
.Where(x => x.Id == id);
答案 1 :(得分:1)
这将递归遍历类别,直到找到类别匹配传递的id(如果有的话)。将返回找到的类别的完整路径(例如,像breadcrumbs菜单一样):
static IEnumerable<Category> GetById(IEnumerable<Category> categories, string id)
{
if (categories == null || !categories.Any())
yield break;
Category result = categories.FirstOrDefault(c => c.Id == id);
if (result != null)
{
yield return result;
yield break;
}
foreach (var category in categories)
{
var subCategories = GetById(category.Categories, id);
if (subCategories.Any()) // we have found the category
{
yield return category; // return current category first
foreach (var subCategory in subCategories)
yield return subCategory;
yield break; // don't search in other categories
}
}
}
用法:
IEnumerable<Category> result = GetById(categories, id);
// Food > Beer > Kilkenny
string breadcrumbs = String.Join(" > ", result.Select(c => c.Name).ToArray());
如果您愿意,可以将此方法转换为扩展名。
答案 2 :(得分:0)
如果你有一个不确定的嵌套级别,你需要通过Categories
递归,即使你有一个固定的嵌套级别,对于任何级别的嵌套级别超过2-3级,它都会值得递归。
Linq并没有真正表达递归的方法,尽管这篇文章谈到了使用Linq2Xml功能来实现它:Expressing recursion in LINQ
如果您能够修改类本身,则可以实现GetChildById
样式方法来递归扫描子Categories
。