Как преобразовать все строки в List <string> в нижний регистр с помощью LINQ?

95

Вчера я увидел фрагмент кода в одном из ответов на StackOverflow, который меня заинтриговал. Это было примерно так:

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

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

Я надеялся, что смогу использовать его для преобразования всех элементов в myList в нижний регистр. Однако этого не происходит ... после запуска этого регистр в myList не изменяется.

Итак, мой вопрос: есть ли способ с помощью LINQ и лямбда-выражений легко перебирать и изменять содержимое списка аналогично этому.

Спасибо Макс

Макс Шиллинг
источник

Ответы:

186

Самый простой подход:

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

Не слишком сильно отличается от вашего примера кода. ForEachзацикливает исходный список, тогда как ConvertAllсоздает новый, который необходимо переназначить.

Джейсон Бантинг
источник
4
Не метод расширения.
leppie
@leppie: Верно, это не так - хороший улов. В этом случае беспокойство о том, является ли это методом экземпляра или методом расширения, может быть немного педантичным, но определенно точным. :)
Джейсон Бантинг
И строка неизменна: P
Шерлок
49

Это потому, что ToLower возвращает строку в нижнем регистре, а не преобразовывает исходную строку. Итак, вам нужно что-то вроде этого:

List<string> lowerCase = myList.Select(x => x.ToLower()).ToList();
Райан Ланди
источник
1
Мне этот подход нравится больше, чем принятый ответ, потому что вы можете использовать его с любым IEnumerable <string>, а не только с List <string>.
Джошуа Печ
6
Это решение также работает в .NET Core, ConvertAll не существует в .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");
}
маркумка
источник
3

ForEachuses Action<T>, что означает, что вы могли бы повлиять, xесли бы он не был неизменным. Поскольку xэто a string, оно неизменяемо, поэтому никакие действия с ним в лямбде не изменят его свойства. Решение Kyralessa - ваш лучший вариант, если вы не хотите реализовать собственный метод расширения, который позволяет вам возвращать значение замены.

Майкл Медоуз
источник
Пожалуйста, проведите дополнительное исследование, если вы не уверены ... что-то помните?
Патрик Дежарден,
Ошибка человеческая, ссылка, которую я предоставил, имела 3.5 жирным шрифтом и 2.0 обычным шрифтом, я ее не видел. Я удалил свой пост ... простого комментария от вас было бы достаточно. Вы хотите проголосовать против без причины, чем предполагаете сейчас.
Патрик Дежарден,
Хотя я пишу это почти год спустя, и хотя я не Даок, я скажу вам, почему ваш ответ «неправильный» - вы сказали, что «решение Киралессы - ваш лучший вариант», когда это не так - мое решение чище и яснее.
Джейсон Бантинг,
-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"))
Ухламурил
источник