Подтвердить что ты не робот

Как использовать LINQ для выбора объекта?

У меня есть данные, которые выглядят так:

UserId   |  SongId
--------   --------
1          1
1          4
1          12
2          95

У меня также есть следующий класс:

class SongsForUser
{
    public int User;
    public List<int> Songs;
}

Что бы я хотел сделать, это использовать LINQ для выбора из моих данных для создания коллекции объектов SongsForUser. Ниже я догадываюсь:

var userCombos = songs.UserSongs.Select(x => new SongsForUser() { User = x.UserId, 
                                                                  Songs = /*What goes here?*/ });

Как бы я начал заполнять список Songs?

Таким образом, результатом должно быть два объекта SongsForUser. Для пользователя 1 у него будет 3 элемента в списке Songs. Для пользователя 2 у него будет 1 элемент в списке Songs.

4b9b3361

Ответ 1

songs.UserSongs.GroupBy(x => x.User).Select(g => new SongsForUser() 
{ 
    User = g.Key,
    Songs = g.Select(s => s.SongId).ToList()
});

Ответ 2

Я подозреваю, что вы хотите:

var songsByUser = songs.UserSongs
                       .GroupBy(song => song.UserId, song => song.SongId)
                       .Select(g => new SongsForUser { User = g.Key,
                                                       Songs = g.ToList() });

Чтобы объяснить, после GroupBy у вас будет группа групп, где ключ каждой группы - это идентификатор пользователя, а значения внутри группы - это идентификаторы песен:

Key = 1, Values = 1, 4, 12
Key = 2, Value = 95

Затем вы просто конвертируете это в свой тип SongsForUser. Обратите внимание, что вам не нужно явно включать () при вызове конструктора в инициализаторе объекта - он неявно, если вам не нужно указывать аргументы конструктора.

Вы можете сделать все это одним вызовом GroupBy, кстати:

var songsByUser = songs.UserSongs
         .GroupBy(song => song.UserId, song => song.SongId,
                  (user, ids) => new SongsForUser { User = user,
                                                    Songs = ids.ToList() });

Лично я обычно нахожу отдельный вызов Select более читабельным.

Вы также можете сделать все это с помощью выражения запроса:

var songsByUser = from song in songs.UserSongs
                  group song.SongId by song.UserId into g
                  select new SongsForUser { User = g.Key, Songs = g.ToList() };

РЕДАКТОР: Вышеупомянутый "нейтральный поставщик", но похоже, что он не работает с LINQ to Entities. Вы можете заставить его работать следующим образом:

var songsByUser = songs.UserSongs
                       .GroupBy(song => song.UserId, song => song.SongId)
                       .AsEnumerable()
                       .Select(g => new SongsForUser { User = g.Key,
                                                       Songs = g.ToList() });

Вызов AsEnumerable заставит группировку выполнить в базе данных, но конечная проекция (включая вызов ToList) будет выполняться локально. Однако вы должны проверить сгенерированный SQL на эффективность.

Ответ 3

Предположим, что у вас есть следующее:

public class SongsForUser
{
    public int UserId;
    public List<int> Songs;
}

Тогда функция, подобная этой, будет выполнена. Список есть некоторые данные для тестирования.

    public void Group()
    {
        List<Tuple<int, int>> SongRelations = new List<Tuple<int, int>>();

        SongRelations.Add(new Tuple<int, int>(1, 1));
        SongRelations.Add(new Tuple<int, int>(1, 4));
        SongRelations.Add(new Tuple<int, int>(1, 12));
        SongRelations.Add(new Tuple<int, int>(2, 95));

        var list = SongRelations.GroupBy(s => s.Item1)
                                .Select(r => new SongsForUser()
                                {
                                    UserId = r.Key,
                                    Songs = r.Select(t => t.Item2).ToList(),
                                });
    }

list содержит 2 элемента типа SongsForUser впоследствии. Один с пользователем 1 и список песен, содержащих 1, 4 и 12 и один с пользователем 2 и список песен, содержащих 95.

Ответ 4

В простейшем виде вы можете просто:

List<MapPoint> points = db.PropertyResearches.Where(a => a.deptId == 66).Select(x => new MapPoint { property = x.notes.Substring(0, 10), latitude = x.lat, longitude = [email protected] }).ToList();