【问题标题】:Is it possible to group a collection when each item could have more than one key?当每个项目可能有多个键时,是否可以对集合进行分组?
【发布时间】:2014-12-18 15:53:54
【问题描述】:

我有一个问题,即给定项目可能有多个键,并且我需要在分组时出现在两个集合中。这可能吗?

这些项目可能看起来像这样

class Item
{
   Category mainCat {get;set;}

   IEnumerable<Category> RelatedCategories {get;set;}

   String RefNumber {get;set;}
}

class Category
{
   String CatName {get;set;}
}

我需要按类别对项目集合进行分组,但如果项目具有相关类别,则它也需要出现在相关类别的组中。

因此,作为一个最简单的示例,我将在集合中有以下项目实例:

参考:A1 类别:Cat_01 相关类别:{Cat_02}

分组后我想要的输出是:

钥匙:Cat_01,物品 {A1} 键:Cat_02,项目 {A1}

这有可能吗?

【问题讨论】:

  • 带你列表追加所有相关类别为新项目,然后分组。

标签: c# linq lambda


【解决方案1】:

是的,您可以通过以下方式进行。

var dictionary = item.RelatedCategories
     .Concat(Enumerable.Repeat(item.mainCat, 1))
     .ToDictionary(c => c.CatName, c => item);

这将获取相关类别并连接主要类别并使用ToDictionary 将每个类别名称与给定项目相关联。

如果您正在处理项目列表,它会变得更加复杂,因为我认为在这种情况下您需要 Dictionary&lt;string, List&lt;Item&gt;&gt;

var dictionary = items.SelectMany(i => i.RelatedCategories
                                        .Concat(Enumerable.Repeat(i.mainCat, 1))
                                        .Select(c => new { c.CatName, Item = i}))
                      .GroupBy(a => a.CatName)
                      .ToDictionary(a => a.Key, a => a.ToList());

这里的内部查询是创建一个匿名类的枚举,这些类将每个类别名称与项目相关联。 SelectMany 会将枚举扁平化为一个。然后GroupBy 将根据类别名称将这些匿名类分组。然后ToDictionary 将创建一个字典,其中键是每个组的键(类别名称),值是与类别名称关联的项目列表。

【讨论】:

  • 哦,没想到用Enumerable.Repeat把单个对象转成枚举。好技巧!
  • 太棒了。以我需要的方式工作。谢谢
【解决方案2】:

所以你有一个Item 引用列表,并且你想要一个包含键(类别)和相关Item 实例的字典。下面的代码会做到这一点。

var dict = new Dictionary<Category, List<Item>>();
foreach (var item in ItemsList)
{
    AddToCategory(item, item.mainCat);
    foreach (var cat in item.RelatedCategories)
    {
        AddToCategory(item, cat);
    }
}

void AddToCategory(Item item, Category cat)
{
    List<Item> categoryItems;
    if (!dict.TryGetValue(cat, out categoryItems))
    {
        categoryItems = new List<Item>();
        dict.Add(cat, categoryItems);
    }
    categoryItems.Add(item);
}

我看不出用简单的 LINQ 表达式来做这件事,尽管很有可能有办法。

【讨论】:

  • 您不需要将字典传递给AddToCategory 方法,还是假设它是全局的。
  • @juharr:这里我假设它是全球性的。否则,是的,你必须通过它。
【解决方案3】:

可以使用 LINQ 查询:

var query = from item in source
            from category in item.RelatedCategories.Concat(new[] { item.MainCat })
            group item by category.CatName into g
            select g;

虽然这是使用 LINQ 可能不是最易读的解决方案的少数情况之一。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-04-20
    • 1970-01-01
    • 2020-03-22
    • 1970-01-01
    • 1970-01-01
    • 2021-08-20
    • 2011-03-16
    • 1970-01-01
    相关资源
    最近更新 更多