Использование условных лямбда-операторов с действием foreach в списке - PullRequest
5 голосов
/ 24 марта 2009

Почему я не могу сделать что-то подобное?

Если у меня есть List<String> myList, заполненный предметами, я хочу иметь возможность воздействовать на каждого участника условным образом, например:

myList.ForEach(a => { if (a.Trim().Length == 0) a = "0.0"; })

Но это не скомпилируется. Я предполагаю, что это связано с отсутствием возвращаемого значения?

Я пытаюсь подготовить список строк для преобразования в double, и я хочу, чтобы на пустых элементах отображалось «0.0», чтобы я мог просто преобразовать весь список за один раз.

Ответы [ 3 ]

6 голосов
/ 24 марта 2009

ForEach не является изменяемым, он никак не меняет структуру данных.

Вы можете либо:

  1. Обрабатывайте цикл самостоятельно, с индексом
  2. Создать новый список, используя .Select и .ToList (при условии, что вы используете .NET 3.5)

Пример # 1:

for (Int32 index = 0; index < myList.Count; index++)
    if (myList[index].Trim().Length == 0)
        myList[index] = "0.0";

С .NET 3.5 и Linq:

myList = (from a in myList
          select (a.Trim().Length == 0) ? "0.0" : a).ToList();

В .NET 3.5 не с использованием синтаксиса Linq, а с использованием кода Linq:

myList = myList.Select(a => (a.Trim().Length == 0) ? "0.0" : a).ToList();

Редактировать : Если вы хотите создать новый список парных чисел, вы также можете сделать это за один раз, используя Linq:

List<Double> myDoubleList =
    (from a in myList
     select (a.Trim().Length == 0 ? "0" : a) into d
     select Double.Parse(d)).ToList();

Обратите внимание, что при использовании «0.0» вместо просто «0» десятичная точка является символом полной остановки. В моей системе это не так, поэтому я заменил его на «0», но более подходящим способом было бы изменить вызов на Double.Parse для получения явного числового форматирования, например:

List<Double> myDoubleList =
    (from a in myList
     select (a.Trim().Length == 0 ? "0.0" : a) into d
     select Double.Parse(d, CultureInfo.InvariantCulture)).ToList();
4 голосов
/ 24 марта 2009

Что вы, возможно, хотите:

public static void MutateEach(this IList<T> list, Func<T, T> mutator)
{
    int count = list.Count;
    for (int n = 0; n < count; n++)
        list[n] = mutator(list[n]);
}

Что позволит:

myList.MutateEach(a => (a.Trim().Length == 0) ? "0.0" : a);

Просто поместите метод MutateEach в свой собственный открытый статический класс и убедитесь, что у вас есть директива using, которая его найдет.

Стоит ли определять что-то подобное, зависит от того, как часто вы будете использовать это. Обратите внимание, что оно должно быть расширением IList вместо IEnumerable, чтобы мы могли выполнять обновления, что делает его менее применимым.

0 голосов
/ 25 октября 2012

@ daniel-earwicker MutateEach Расширение является хорошим решением.


Хотя для возврата нового List у вас есть возможность использовать List.ConvertAll<TTo>(Converter<TFrom,TTo>(Func<TFrom, TTo>)), который существует с .NET 2.0.

Это не Linq или Lambda .

List<String> nodeStringList = new List<String>(new String[] { "", "0.5 ", " 1.1"}); 

nodeStringList = nodeStringList.ConvertAll<String>((c) => (c.Value.Trim().Length != 0) ? c.Value.Trim() : "0.0");

Ссылка MSDN - List.ConvertAll

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...