#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) { Listphones = 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 IEnumerableUpdate (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();
Комментариев нет:
Отправить комментарий