Jak przekonwertować wszystkie ciągi w List <string> na małe litery przy użyciu LINQ?

94

Widziałem wczoraj fragment kodu w jednej z odpowiedzi na StackOverflow, który mnie zaintrygował. To było coś takiego:

 List<string> myList = new List<string> {"aBc", "HELLO", "GoodBye"};

 myList.ForEach(d=>d.ToLower());

Miałem nadzieję, że uda mi się go użyć do przekonwertowania wszystkich elementów w myList na małe litery. Jednak tak się nie dzieje ... po uruchomieniu tego, obudowa w myList pozostaje niezmieniona.

Moje pytanie brzmi więc, czy istnieje sposób użycia wyrażeń LINQ i Lambda do łatwego iterowania i modyfikowania zawartości listy w sposób podobny do tego.

Dzięki, Max

Max Schilling
źródło

Odpowiedzi:

185

Najłatwiejsze podejście:

myList = myList.ConvertAll(d => d.ToLower());

Nie różni się zbytnio od przykładowego kodu. ForEachzapętla oryginalną listę, podczas gdy ConvertAlltworzy nową, którą musisz ponownie przypisać.

Jason Bunting
źródło
4
Nie jest to metoda rozszerzenia.
leppie
@leppie: To prawda, nie jest - dobry chwyt. W tym przypadku martwienie się, czy jest to metoda instancji, czy metoda rozszerzająca, może być nieco pedantyczne, ale jest zdecydowanie dokładne. :)
Jason Bunting
A ciąg jest niezmienny: P
Sherlock,
49

Dzieje się tak, ponieważ ToLower zwraca ciąg z małych liter, zamiast konwertować oryginalny ciąg. Więc chciałbyś coś takiego:

List<string> lowerCase = myList.Select(x => x.ToLower()).ToList();
Ryan Lundy
źródło
1
Takie podejście podoba mi się bardziej niż zaakceptowana odpowiedź, ponieważ możesz jej użyć z dowolnym IEnumerable <string>, a nie tylko List <string>.
Joshua Pech
6
To rozwiązanie działa również w .NET Core, ConvertAll nie istnieje w .NET Core.
Jonas,
3
[TestMethod]
public void LinqStringTest()
{
    List<string> myList = new List<string> { "aBc", "HELLO", "GoodBye" };
    myList = (from s in myList select s.ToLower()).ToList();
    Assert.AreEqual(myList[0], "abc");
    Assert.AreEqual(myList[1], "hello");
    Assert.AreEqual(myList[2], "goodbye");
}
marcumka
źródło
3

ForEachużywa Action<T>, co oznacza, że ​​mógłbyś wpłynąć, xgdyby nie był niezmienny. Ponieważ xjest a string, jest niezmienna, więc nic, co zrobisz z nim w lambdzie, nie zmieni jego właściwości. Rozwiązanie Kyralessa jest najlepszą opcją, chyba że chcesz zaimplementować własną metodę rozszerzenia, która umożliwia zwrócenie wartości zastępczej.

Michael Meadows
źródło
Jeśli nie jesteś pewien, zbierz więcej informacji ... pamiętasz coś?
Patrick Desjardins,
Błąd jest ludzki, link, który podałem, miał 3,5 pogrubioną czcionką i 2,0 normalnie, nie widziałem. Usunąłem swój post ... wystarczyłby prosty komentarz od Ciebie. Chcesz głosować przeciw bez powodu, niż teraz załóż.
Patrick Desjardins
Chociaż piszę to prawie rok później i chociaż nie jestem Daokiem, powiem ci, dlaczego twoja odpowiedź jest „zła” - powiedziałeś „rozwiązanie Kyralessy jest najlepszą opcją”, gdy tak nie jest - moje rozwiązanie jest czystsze i jaśniejsze.
Jason Bunting
-1
var _reps = new List(); // with variant data

_reps.ConvertAll<string>(new Converter<string,string>(delegate(string str){str = str.ToLower(); return str;})).Contains("invisible"))
Uhlamurile
źródło