Несколько СУММИРУЮТ использование LINQ

У меня есть цикл как следующее, я могу сделать то же использование, несколько СУММИРУЮТ?

foreach (var detail in ArticleLedgerEntries.Where(pd => pd.LedgerEntryType == LedgerEntryTypeTypes.Unload &&
                                                                pd.InventoryType == InventoryTypes.Finished))
{
     weight += detail.GrossWeight;
     length += detail.Length;
     items  += detail.NrDistaff;
}
10
задан Robert Harvey 9 November 2009 в 22:10
поделиться

4 ответа

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

public static class EnumerableExtensions
{
    public static void Each<T>(this IEnumerable<T> col, Action<T> itemWorker)
    {
        foreach (var item in col)
        {
            itemWorker(item);
        }
    }
}

И называть его так:

// Declare variables in parent scope
double weight;
double length;
int items;

ArticleLedgerEntries
    .Where(
        pd => 
           pd.LedgerEntryType == LedgerEntryTypeTypes.Unload &&
           pd.InventoryType == InventoryTypes.Finished
    )
    .Each(
        pd => 
        {
            // Close around variables defined in parent scope
            weight += pd.GrossWeight; 
            lenght += pd.Length;
            items += pd.NrDistaff;
        }
    );

UPDATE: Еще одно примечание. В приведенном выше примере используется закрытие. Переменные weight, length и items должны быть объявлены в родительской области, что позволит им сохраняться после каждого вызова действия itemWorker. Я обновил пример, чтобы отразить это для ясности.

8
ответ дан 3 December 2019 в 22:37
поделиться

Вы могли бы сделать этот стиль сводной таблицы, используя ответ в этой теме: Можно ли сводить данные с помощью LINQ?

0
ответ дан 3 December 2019 в 22:37
поделиться

Вы можете вызвать Sum три раза, но это будет медленнее, потому что будет выполнено три цикла.

Например:

var list = ArticleLedgerEntries.Where(pd => pd.LedgerEntryType == LedgerEntryTypeTypes.Unload
                                   && pd.InventoryType == InventoryTypes.Finished))

var totalWeight = list.Sum(pd => pd.GrossWeight);
var totalLength = list.Sum(pd => pd.Length);
var items = list.Sum(pd => pd.NrDistaff); 

Из-за отложенного выполнения он также будет повторно оценивать вызов Where каждый раз, хотя в вашем случае это не такая проблема. Этого можно было бы избежать, вызвав ToArray , но это вызовет выделение массива. (И все равно будет выполняться три цикла)

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


EDIT : Если вы действительно хотите использовать LINQ, вы можете неправильно использовать Aggregate , например так:

int totalWeight, totalLength, items;

list.Aggregate((a, b) => { 
    weight += detail.GrossWeight;
    length += detail.Length;
    items  += detail.NrDistaff;
    return a;
});

Это феноменально уродливый код, но он должен работать почти так же хорошо, как прямой цикл.

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

var totals = list.Aggregate(
    new { Weight = 0, Length = 0, Items = 0},
    (t, pd) => new { 
        Weight = t.Weight + pd.GrossWeight,
        Length = t.Length + pd.Length,
        Items = t.Items + pd.NrDistaff
    }
);
5
ответ дан 3 December 2019 в 22:37
поделиться

Хорошо. Я понимаю, что сделать это с помощью LINQ непросто. Я возьму цикл may foreach, потому что понял, что это не так уж и плохо. Спасибо всем вам

0
ответ дан 3 December 2019 в 22:37
поделиться
Другие вопросы по тегам:

Похожие вопросы: