#c# #linq
#c# #linq
Вопрос:
[Отредактировано и добавлена дополнительная соответствующая информация]
Я хотел бы знать, как вы лучше справляетесь с этим сценарием. Вместо того, чтобы повторять каждое значение (или суммировать по groupby), я хочу один метод «разница между последним / первым». Возможно, стоит упомянуть, что отсутствующие поля (примеры ниже) сначала добавляются динамически (но, тем не менее, их внешний вид оценивается как «отсутствующий».
Пример, диапазон здесь состоит из дат (но может быть месяцем, минутами, часами).
Получить сумму значений между каждым шагом в диапазоне.
Выборка данных для вычисления:
<missing>
2011-01-02 4.5 user1
2011-01-02 1.5 user2
2011-01-03 4.7 user1
2011-01-03 1.6 user2
2011-01-04 4.9 user1
2011-01-04 1.7 user2
2011-01-05 6.1 user1
2011-01-05 1.8 user2
<missing>
2011-01-06 1.9 user2
2011-01-07 6.5 user1
2011-01-07 2.0 user2
2011-01-08 6.9 user1
2011-01-08 2.1 user2
2011-01-09 7.0 user1
2011-01-09 2.2 user2
<missing>
<missing> ..
Значения в этой таблице приведены в кумулятивном порядке. Это означает, что они увеличиваются как таймер, который Бен запускал / останавливал несколько раз, но никогда не запускал повторно.
Если get 20110101--20110131"
был задан диапазон, метод ответит "2011-01-01 3,2"
Если был запрошен точный период get 20110107
, был запрошен метод "2011-01-07 0.5"
. Результат равен 0,5, потому 20110708 user1 6.9
что минус 20110707 user1 6.5
== 0,4 и 20110708 user2 2.1
минус 20110707 user2 2.0
== 0,1. Затем сложите 0.4 0.1
вместе.
Это будет проблемой, когда я захочу вернуть массив вычисленных последних / первых значений. Если я хочу, чтобы сумма между каждым днем в заданном диапазоне 20110101—20110131, должна "sum between last/first value"
ли она выполняться в каждый день в диапазоне.
Результат такой
2011-01-02 0.3
2011-01-03 0.3
2011-01-04 1.3
2011-01-05 0
2011-01-06 0.1
2011-01-07 0.5
2011-01-08 0.2
2011-01-09 0
2011-01-10 0
2011-01-11 0 ..
Пропущенные периоды (дни) в диапазоне приведут к нулю в качестве результата. Я имею в виду, что сумма между 20110104 —20110105 не может быть иной, чем ноль (из-за пропущенного значения). Хотя, если вы берете сумму между 20110104-20110107, вы не распознаете недостающие значения между ними.
Комментарии:
1. Может быть, это только я, но я просто не понимаю. Я перечитал ваш вопрос 3 раза, и это просто не имеет для меня никакого смысла. Пожалуйста, перефразируйте / уточните свое намерение.
2. @Jonas, ты можешь начать с объяснения, как
get 20110107
=2011-01-07 0.5
. Возможно, это поможет нам понять.3. Да, черт возьми, извините! Я только что узнал это. Возьмите (20110708 user1 6,9) минус (20110707 user1 6,5) == 0,4. Затем то же самое для user2 (что равно 0.1), затем добавьте 0.4 0.1 вместе.
Ответ №1:
Хорошо, это решено, но на самом деле это не единственное решение вопросов и ответов..
Некоторый псевдокод,
ConsumptionOfRange(List someList, Enum somePeriod)
{
foreach (var user in someList.groupBy(d=>d.Name)
{
MethodToFillGapsInRange(ref someList)
foreach (var period in someList.GroupBy(d => d.Date.Date))
{
// Kind of magic here. Ticks is the "weight" of the period somePeriod.
// This make query know where in future to look for next valid value.
var localValues =
(from mv in someList
where mv.Date == period.Key
|| mv.Date.Date == period.Key.AddTicks(Method(somePeriod).Ticks)
select mv).ToList();
// At this place, call the generic function used to calculate range.
result.Add(ConsumptionRange(dc));
}
}
}
//That generic function looks like this.
//Called directly calculating differences between big ranges (1000 or a million of records)
public AClass ConsumptionOfRange(List someValues)
{
AClass grouped =
(from d in someValues.OrderBy(d=>d.Date)
group d by d.Name into gr
select new VC
{
Name = gr.FirstOrDefault().Name,
Date = gr.FirstOrDefault().Date,
Value =
(gr.LastOrDefault().Value
- gr.FirstOrDefault().Value)
}).FirstOrDefault();
return grouped;
}
Ответ, вероятно, не сильно поможет другому, но, возможно, некоторая семантика может быть повторно использована для последующих посетителей этого Q. Или, может быть, я могу выучить еще один урок, чтобы сделать это лучше.