У меня есть цикл как следующее, я могу сделать то же использование, несколько СУММИРУЮТ?
foreach (var detail in ArticleLedgerEntries.Where(pd => pd.LedgerEntryType == LedgerEntryTypeTypes.Unload &&
pd.InventoryType == InventoryTypes.Finished))
{
weight += detail.GrossWeight;
length += detail.Length;
items += detail.NrDistaff;
}
С технической точки зрения то, что у вас есть, вероятно, является наиболее эффективным способом сделать то, что вы просите. Однако вы можете создать метод расширения в IEnumerable
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. Я обновил пример, чтобы отразить это для ясности.
Вы могли бы сделать этот стиль сводной таблицы, используя ответ в этой теме: Можно ли сводить данные с помощью LINQ?
Вы можете вызвать 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
}
);
Хорошо. Я понимаю, что сделать это с помощью LINQ непросто. Я возьму цикл may foreach, потому что понял, что это не так уж и плохо. Спасибо всем вам