Как группировать товары по внутреннему списку

2

Я хочу сгруппировать список User по их Group.
Пользователь может быть в нескольких группах.

public class User
{
    public string Username { get; set; }
    public List<Group> Groups { get; set; }
}

BusinessLogic возвращает мне List<User>.
Вместо того, чтобы пользователи имеют свои группы, мне нужно реформировать этот список, чтобы группы содержали пользователей.

Пример:
Группа 1:
- Пользователь 1
- Пользователь 2
Группа 2:
- Пользователь 1
- Пользователь 3
Группа 3:
- Пользователь 2
- Пользователь 3

Я застрял на том методе расширения, который мне нужно использовать, поэтому я не уверен, что искать.
Я бы предположил метод GroupBy но после этого я потерялся :)

Теги:
linq

2 ответа

3
Лучший ответ

Используйте SelectMany для сглаживания вложенных коллекций, извлекают кортежи пользователя и группы. Таким образом, использование, содержащее много групп, приведет к многократной записи. Следующая группа записывает группу и сохраняет пользователя в качестве элементов в группе

var result = userList.SelectMany(user => user.Groups.Select(group => (user,group)))
                     .GroupBy(item => item.group, item => item.User);

В текущей реализации, так как группа выполняется над объектом Group, этот объект должен реализовывать Equals и GetHashCode. Если вы не хотите этого делать, существует перегрузка, которая также получает IEqualityComparer. Подробнее см. В документации.

Обратите внимание на использование Named Tuples. Если вы используете С# до 7.0, вы можете спроектировать анонимный объект или явно инициализировать кортеж, а затем изменить способ доступа к свойствам - Item1 и Item2.

1

Решение, предложенное в принятом ответе, не работает. Мое решение:

var result1 = from user in users
              from grp in user.Groups
              group user by grp into pivot
              select pivot;

Исправлена версия кода Gilad:

var result = users.SelectMany(user => user.Groups,(user, group)=>(user,group))
                          .GroupBy(item => item.group,item=>item.user);

Полный код моего и Гилада:

static void Main(string[] args)
{
    Group group1 = new Group("Group1");
    Group group2 = new Group("Group2");
    Group group3 = new Group("Group3");
    List<User> users = new List<User>(new User[] {
        new User() { Username = "User1", Groups = new List<Group>(new Group[] { group1,group2})  },
        new User() { Username = "User2", Groups = new List<Group>(new Group[] { group1,group3})  },
        new User() { Username = "User3", Groups = new List<Group>(new Group[] { group2,group3})  }
    });
    var result1 = from user in users
                 from grp in user.Groups
                 group user by grp into pivot
                 select pivot;
    foreach (var r in result1)
    {
        Console.WriteLine(r.Key.Name);
        foreach (var u in r)
            Console.WriteLine(u.Username);
    }

    Console.WriteLine();
    var result = users.SelectMany(user => user.Groups.Select(group => (user, group))
              .GroupBy(item => item.group,item=>item.user));
    foreach (var r in result)
    {
        Console.WriteLine(r.Key.Name);
        foreach (var u in r)
            Console.WriteLine(u.Username);
    }


    Console.ReadKey();
}

public class Group : IEquatable<Group>
{
    public Group(string name)
    {
        Name = name;
    }
    public string Name { get; set; }

    public bool Equals(Group other)
    {
        return other.Name == Name;
    }

    public override bool Equals(object obj)
    {
        return ((Group)obj).Name==Name;
    }

    public override int GetHashCode()
    {
        return Name.GetHashCode();
    }
}
public class User
{
    public string Username { get; set; }
    public List<Group> Groups { get; set; }
}

Выход (сначала мой код, второй вывод кода Gilad):

Group1
User1
User2
Group2
User1
User3
Group3
User2
User3

Group1
User1
Group2
User1
Group1
User2
Group3
User2
Group2
User3
Group3
User3
  • 0
    Вы правы, что код не сработал так, как задумывалось, но он поставил меня на правильный путь. Я, который я мог принять оба ответа :)

Ещё вопросы

Сообщество Overcoder
Наверх
Меню