Страницы

Поиск по вопросам

пятница, 14 февраля 2020 г.

В C# необходимо отредактировать несколько элементов коллекции через LINQ запрос

#c_sharp #linq #коллекции


Язык C#, LINQ, Работа с несколькими элементами коллекции элементов.

Уважаемые коллеги прошу о помощи!
Есть коллекция элементов. Мне необходимо выбрать все элементы с "Company=Microsoft"
и изменить в этой же коллекции на "Company=12345" через LINQ запрос.

Код:

namespace GroupByLinq
{
    class Phone
    {
        public string Name { get; set; }
        public string Company { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            List phones = new List
            {
                new Phone {Name="Lumia 430", Company="Microsoft" },
                new Phone {Name="Mi 5", Company="Xiaomi" },
                new Phone {Name="LG G 3", Company="LG" },
                new Phone {Name="iPhone 5", Company="Apple" },
                new Phone {Name="Lumia 930", Company="Microsoft" },
                new Phone {Name="iPhone 6", Company="Apple" },
                new Phone {Name="Lumia 630", Company="Microsoft" },
                new Phone {Name="LG G 4", Company="LG" }
            };


            //Вот здесь что-то необходимо поправить или присвоения вовсе не должно быть
            phones = phones.SelectMany(x => x.Company == "Microsoft", p => new Phone
{ Name = p.Name, Company = "Citrus" }).ToList();


            foreach (Phone g in phones)
                Console.WriteLine(g.Company + " / " + g.Name);

            Console.Read();
        }
    }
}

    


Ответы

Ответ 1



Linq не предназначен для изменения данных, он используется для запросов, поэтому я рекомендую вам воспользоваться обычным циклом, но если очень захотеть, можно написать примерно так: phones = phones .Select(p => p.Company == "Microsoft" ? new Phone { Name = p.Name, Company = "12345" } : p) .ToList(); Этот подход плох тем, что он не изменяет старые объекты, а создает новые: а) вы должны учесть что где-то могут остаться ссылки на старые phone, которых теперь нет в новой коллекции; б) если вы добавите в класс новые свойства - вам придется найти каждый такой запрос и откорректировать его. Подумайте хорошенько и поймете, что такой вариант будет гораздо лучше (да и, кстати, не сильно многословнее): for (int i = 0; i < phones.Count; ++i) if (phones[i].Company == "Microsoft") phones[i].Company = "12345"; и да, с помощью Linq вы можете выбрать нужные телефоны и итерировать по ним, это тоже корректное решение (объекты остаются те же самые, с помощью Linq выбираем из них нужные): foreach (var phone in phones.Where(p => p.Company == "Microsoft")) phone.Company = "12345"; А в идеале вам вообще нужно завести отдельный класс для компаний, а в телефоне иметь ссылку на него, тогда смена наименования компании превратится во что-то такое: var company = companies.First(c => c.Name == "Microsoft"); company.Name = "12345";

Ответ 2



phones.Where(x => x.Company.Equals("Microsoft")).ToList().ForEach(y => y.Company = "12345");

Ответ 3



простой вариант такой: foreach (Phone g in phones.Where(x => x.Company == "Microsoft")) g.Company = "12345"; также можно воспользоваться методом расширения: public static IEnumerable Update(this IEnumerable source, Action act) { foreach (T element in source) { act(element); } return source; } тогда вызов будет похож на linq: phones.Where(p => p.Company == "Microsoft").Update(p => p.Company = "12345"); Стоит помнить, что в обоих вариантах, будут изменены сами значения переменных типа Phone в списке. Даже без присвоения результата переменной phones

Ответ 4



just my 5 cents: если можно MoreLinq использовать, то вот ещё способ phones = phones .Pipe(x => { if (x.Company.Equals("Microsoft")) x.Company = "13245"; }); или как то так: phones = phones .Pipe(x => x.Company = x.Company.Equals("Microsoft") ? "12345" : x.Company); Плюс такого подхода в том что над каждым элементом выполняется определённый Action, а не создается новый инстанс. Хотя тот же ForEach() делает тоже самое только на List<> - Pipe же можно вызвать на IEnumerable<> Минус подхода - сторонняя библиотека кода (можно без проблем написать свою реализацию Pipe-а). Хотя она за частую полезная.

Ответ 5



Можно каждый элемент списка вкинуть в анонимный метод: phones=phones.Select(x=> { x.Company=x.Company=="Microsoft"?"Citrus":x.Company; return x; }).ToList();

Комментариев нет:

Отправить комментарий