Выражение Linq, чтобы установить для всех значений массива заданное значение. - PullRequest
11 голосов
/ 12 сентября 2009

У меня есть немного кода, который я хотел бы превратить в выражение linq (желательно с лямбдами), чтобы его было проще использовать в качестве делегата. Код выглядит так:

List<DateTime[]> changes = new List<DateTime[]>();
changes = PopulateChanges();
for (int i = 0; i < changes.Count; i++)
{
    for(int j = 0; j < changes[i].Length; j++)
    {
        changes[i][j] = DateTime.MinValue;
    }
}

Для жизни я не могу понять это. Я пытался использовать ForEach и различные формы выбора и т. Д., Кажется, ничего не работает правильно.

К вашему сведению, я знаю, что DateTime по умолчанию имеет значение MinValue, в действительности это очищает массивы по умолчанию после того, как они уже были установлены.

Может кто-нибудь помочь мне с рабочим выражением?

EDIT:

Полагаю, здесь я действительно хочу сказать, что я хочу получить краткий способ установить все элементы многомерного массива на заданное значение. Конечно, вложенный цикл работает, и я, безусловно, могу поместить его в функцию (что я уже сделал). Я просто хочу что-то более лаконичное, чтобы его можно было легко использовать в делегате без создания многострочного монстра.

Ответы [ 5 ]

14 голосов
/ 12 сентября 2009

Это должно сработать.

Это не LINQ, и оно не сильно отличается от ваших вложенных циклов for, просто немного менее многословно.

changes.ForEach(x => Array.Clear(x, 0, x.Length));

Конечно, есть способы (ab) использовать LINQ для достижения тех же результатов, но я бы посчитал их грязными хаки. Кроме того, эквивалент LINQ, вероятно, не будет столь же многословным, как мой пример выше.

2 голосов
/ 12 сентября 2009

Интересный вопрос, но Linq о запрашивает , и то, что вы здесь делаете, не похоже на запрос для меня. Даже если есть решение, я не уверен, что использовал бы Linq для чего-то подобного.

2 голосов
/ 12 сентября 2009

LINQ на самом деле не предназначен для обновления коллекций. Речь идет о запросах, то есть о создании перечислимых по существующим коллекциям. Я думаю, что ваш код отлично читается и не улучшится, если вы заставите его иметь много лямбд и тому подобное.

Если вы хотите создать новый List<DateTime[]> с каждым элементом, установленным в значение, вы можете сделать это:

var changes = Enumerable.Range(0, width)
                        .Select(x => Enumerable.Range(0, height)
                                               .Select(y => DateTime.MinValue)
                                               .ToArray())
                        .ToList();

Если вы действительно хотите сделать это с помощью ForEach / LINQ, возможно злоупотреблять Select (но я не рекомендую это):

changes.ForEach(array => array.Select((dt, i) => array[i] = DateTime.Now)
                              .LastOrDefault());
0 голосов
/ 12 сентября 2009

Всегда есть лучшие практики и тому подобное, но я не знаю, согласен ли я со всем, что все говорили ...

Если я вас правильно понимаю, вы должны перечислить ваш вложенный массив по нескольким причинам и хотели бы инкапсулировать эту функциональность для повторного использования. Есть несколько различных способов сделать это, но вот один из них с использованием linq и один без ... .

List<DateTime[]> changes = new List<DateTime[]>();
changes = PopulateChanges();

// *** As pointed out ForEach this will not change the value in the array, Thanks!***
changes.ForEach(change => change.ToList().ForEach(date => date = DateTime.MinValue));

// this how ever works but is kind of confusing...
changes = changes.Select(change => change.Select(date => DateTime.MinValue).ToArray()).ToList();
//Even that would get old writing it over and over again...

Я бы сделал это так ...

private void ForEachOnNestedDates(List<DateTime[]> list, Func<DateTime, DateTime> method)
{
   // Use your code...
   for (int i = 0; i < list.Count; i++)
   {
      for(int j = 0; j < list[i].Length; j++)
      {
          list[i][j] = method.Invoke(list[i][j]);
      }
   }
}

это позволит вам повторно использовать это и делать разные вещи для каждого элемента. напр.

//Add a Day to each datetime value
ForEachOnNestedDates(changes, (DateTime date) => date.AddDays(1));

//You also make it even more readable
ForEachOnNextedDates(changes, DoSomethingWithDate);

private DateTime DoSomethingWithDate(DateTime value)
{

}

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

0 голосов
/ 12 сентября 2009

Можете ли вы описать некоторые варианты использования предложенного делегата?

Я имею в виду, если PopulateChanges () возвращает вам массив List <> массивов DateTime, и вы просматриваете все из них и устанавливаете их в DateTime.MinValue, что именно является единицей кода, которую вы хотите поместить в делегировать?

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