1

私は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オブジェクトツリーの深さ、おそらく3、4、または5層の特定の層を効果的にクエリするにはどうすればよいですIdか(最大で3層ありますが、将来の参照用に知りたいです)。

編集

さらに、サブカテゴリの深さが3層Categoryしかない場合、オブジェクトツリー全体をトップレベルまで取得するにはどうすればよいですか?Id

4

3 に答える 3

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;
}

次に、LinqIEnumerable<Category>を好きなように使用します。

var filtered = categoryList.SelectMany(x => x.Flatten())
                           .Where(x => x.Id == id);
于 2012-12-08T07:38:47.377 に答える
1

これにより、渡されたIDに一致するカテゴリが見つかるまで(存在する場合)、カテゴリが再帰的にトラバースされます。見つかったカテゴリへのフルパスが返されます(つまり、ブレッドクラムメニューのように):

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());

必要に応じて、このメソッドを拡張機能に変換できます。

于 2012-12-08T08:40:37.503 に答える
0

ネストのレベルが不確定な場合は、再帰する必要がありCategoriesます。ネストのレベルが固定されている場合でも、2〜3レベル以上のネストのレベルでは、再帰する価値があります。

この投稿では、Linq2Xml機能を使用して再帰を表現する方法について説明していますが、Linqには実際には再帰を表現する方法がありません。LINQで再帰を表現する

クラス自体を変更できる場合は、GetChildById-styleメソッドを実装して、子を再帰的にスキャンできますCategories

于 2012-12-08T01:08:43.197 に答える