试图找出一个c# linq的对象列表,可以用多个类别标记,

utugiqy6  于 2024-01-03  发布在  C#
关注(0)|答案(3)|浏览(211)

| 实体清单|标签类别|
| --|--|
| entity1|(cat1,cat2,cat3)|
| 实体2|(cat2,cat4,cat5)|
| 实体3|(cat1,cat3,cat5)|
| 实体4|(cat2,cat3)|
| 实体5|(cat1,cat4,cat5)|

  1. Class Entity
  2. {
  3. Entity Name;
  4. List<Category> Categories
  5. }
  6. var listentities= somemethod(); //returns List<Entity> <br>

字符串
预期产出:
| - -|- -|
| --|--|
| cat1|实体1、实体3、实体5|
| cat2|实体2,实体4|
| cat3|实体1、实体3、实体4|
注意:我使用2个foreach循环和字典得到了想要的输出,但是我想使用linq。

m3eecexj

m3eecexj1#

为了直接回答你的问题,你可以使用SelectManyDistinct来得到你想要的,尽管正如我的评论所说,它可能不会比你已经做的更快:

  1. Entity[] entities = [
  2. new("Ent 1", ["1", "2", "3"]),
  3. new("Ent 2", ["2", "4", "5"]),
  4. new("Ent 3", ["1", "3", "5"]),
  5. new("Ent 4", ["2", "3", ]),
  6. new("Ent 5", ["1", "4", "5"]),
  7. ];
  8. var categories1 = entities
  9. .SelectMany(q => q.Categories)
  10. .Distinct()
  11. .Select(q => new Category(
  12. q,
  13. entities
  14. .Where(w => w.Categories.Contains(q))
  15. .Select(q => q.Name)
  16. .ToList()));
  17. foreach (var cat in categories1)
  18. {
  19. Console.WriteLine($"{cat.Name}: {string.Join(", ", cat.Entities)}");
  20. }
  21. public record Entity(string Name, List<string> Categories);
  22. public record Category(string Name, List<string> Entities);

字符串

展开查看全部
qybjjes1

qybjjes12#

或许:

  1. listentities
  2. .SelectMany(e => e.Categories.Select(c => new {
  3. Entity = e,
  4. Category = c
  5. })
  6. .GroupBy(ec => ec.Category)
  7. .Select(g => new {
  8. Category = g.Key,
  9. Entities = g.Select(ec => ec.Entity).ToList()
  10. })
  11. .ToList();

字符串
这将实体数据扩展为{实体,类别}对,按类别分组,然后构建结果。
如果需要的话,最终的结果可以调整为只包含名称而不是对象引用。此外,如果你想的话,实体名称可以使用.Aggregate()String.Join()连接到一个字符串中。

  • 不确定.GroupBy(ec => ec.Category)。如果Category不是IEquatable,则可能需要.GroupBy(ec => ec.Category.Name),在这种情况下,后面的Category = g.Key需要更改为Category = g.First().Category。*
展开查看全部
hujrc8aj

hujrc8aj3#

我将Entity类定义为

  1. public class Entity(string name, List<string> categories)
  2. {
  3. public string Name { get; } = name;
  4. public List<string> Categories { get; } = categories;
  5. }

字符串
如果类别是自定义类型,则可能需要将其等同。
我将测试SomeMethod方法定义为

  1. static List<Entity> SomeMethod()
  2. {
  3. return new List<Entity>{
  4. new Entity("Ent 1", new List<string> { "1", "2", "3", }),
  5. new Entity("Ent 2", new List<string> { "2", "4", "5", }),
  6. new Entity("Ent 3", new List<string> { "1", "3", "5", }),
  7. new Entity("Ent 4", new List<string> { "2", "3", }),
  8. new Entity("Ent 5", new List<string> { "1", "4", "5", }),
  9. };
  10. }

双循环-无Linq

首先,一种不使用Linq的方法。

  1. var listEntities = SomeMethod();
  2. var dict = new Dictionary<string, IList<Entity>>();
  3. foreach (var entity in listEntities)
  4. {
  5. foreach (var category in entity.Categories)
  6. {
  7. if (!dict.TryGetValue(category, out var value))
  8. {
  9. value = new List<Entity>();
  10. dict.Add(category, value);
  11. }
  12. value.Add(entity);
  13. }
  14. }
  15. foreach (var key in dict.Keys)
  16. {
  17. Console.WriteLine($"{key}: {string.Join(", ", dict[key].Select(e => e.Name))}");
  18. }


基本上,循环遍历Entity对象的列表,并循环遍历Entity对象中的类别以填充Dictionary。

Linq

这一次,使用Linq。

  1. var listEntities = SomeMethod();
  2. var groupByCategory =
  3. listEntities.SelectMany(e => e.Categories.Select(c => new { Category = c, Entity = e, }))
  4. .GroupBy(ce => ce.Category, (cat, ents) => new { Category = cat, Entities = ents });
  5. foreach (var group in groupByCategory)
  6. {
  7. Console.WriteLine($"{group.Category}: {string.Join(", ", group.Entities.Select(e => e.Entity.Name))}");
  8. }


GroupBy的返回值大致相当于字典,可以通过提供resultSelector来“清理”一下。
这两种方法都产生以下输出:

  1. 1: Ent 1, Ent 3, Ent 5
  2. 2: Ent 1, Ent 2, Ent 4
  3. 3: Ent 1, Ent 3, Ent 4
  4. 4: Ent 2, Ent 5
  5. 5: Ent 2, Ent 3, Ent 5

展开查看全部

相关问题