Как я могу получить промежуточные итоговые значения из List ()? - PullRequest
3 голосов
/ 18 января 2011

Список имеет объект, который имеет следующие свойства:

public class PropertyDetails
{

 public int Sequence { get; set; }

 public int Length { get; set; }

 public string Type { get; set; }

 public int Index { get; set; }

}

Список будет отсортирован Последовательность.

Список имеет следующие значения объекта:

Последовательность = 1 Длина = 20 Тип = "" Индекс = 0

Последовательность = 2 Длина = 8 Тип = "" Индекс = 0

Последовательность = 3 Длина = 6 Тип = "" Индекс = 0

Последовательность = 4 Длина = 20 Тип = "" Индекс = 0

Последовательность = 5 Длина = 8 Тип = "" Индекс = 0

Я хочу запрос Linq, который выдаст мне список результатов как

Sequence = 1 Length = 20Type = "" Index = 20

Последовательность = 2 Длина = 8 Тип = "" Индекс = 28

Последовательность = 3 Длина = 6 Тип = "" Индекс = 34

Последовательность = 4 Длина = 20 Тип = "" Индекс = 54

Последовательность = 5 Длина = 8 Тип = "" Индекс = 62

Где индекс - совокупная сумма длины с учетом последовательности.

Ответы [ 3 ]

9 голосов
/ 18 января 2011

Я никогда не говорил этого, но я нахожу решение Джона слишком трудоемким.Скорее я нахожу, что LINQ - неправильное решение этой проблемы.Вы хотите манипулировать состоянием, не подходящим для традиционных операторов LINQ.

Я бы просто сделал это:

var sum = 0;
foreach (var p in list) {
  sum += p.Length;
  p.Index = sum;
}

LINQ - это молоток.Убедитесь, что вы используете правильный инструмент для решения проблемы, а не просто попросите совета.

3 голосов
/ 18 января 2011

Там нет стандартного оператора LINQ, который делает это - в основном вы хотите запустить агрегацию. Вы можете подделать его с помощью запроса с побочными эффектами на данный момент, но это все.

К счастью, для этого легко написать собственный оператор запроса. Что-то вроде:

public static IEnumerable<TResult> Scan<TSource, TResult>(
    this IEnumerable<TSource> source,
    TResult seed,
    Func<TResult, TSource, TResult> func)
{
    TResult current = seed;
    // TODO: Argument validation
    foreach (TSource item in source)
    {
        current = func(current, item);
        yield return current;
    }
}

Тогда вы можете использовать:

var query = list.Scan(new PropertyDetails(),
                      (current, item) => new PropertyDetails { 
                           Sequence = item.Sequence,
                           Length = item.Length,
                           Index = current.Index + item.Length
                      });

РЕДАКТИРОВАТЬ: я не проверял детали, но я считаю, что Reactive Extensions имеет аналогичный метод в своей System.Interactive сборки.

0 голосов
/ 18 января 2011

Может быть что-то вроде этого (это не очень читабельно):

var newList = list.Select(x =>
                        new PropertyDetails()
                        {
                            Type = x.Type,
                            Length = x.Length,
                            Sequence = x.Sequence,
                            Index = list.Take(x.Sequence).Select(y => y.Length).Aggregate((a, b) => a + b)
                        }
);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...