Reputation: 6908
I have the following method in my project:
public double CalculateDailyProjectMaxPumpSpm(DateTime date, string start = null, string end = null)
{
Log("Calculating Daily Pump stroke Max...");
var spm = new List<double>();
if (start == null)
{
for (var i = 0; i < _pumpOneSpm.Count; i++)
{
if (_date[i].Equals(date))
{
spm.Add(_pumpOneSpm[i]);
spm.Add(_pumpTwoSpm[i]);
}
}
}
else
{
for (var i = 0; i < _pumpOneSpm.Count; i++)
{
if (_date[i].Equals(date) &&
DateTime.Compare(_time[i], DateTime.Parse(start)) > 0 &&
DateTime.Compare(_time[i], DateTime.Parse(end)) < 0)
{
spm.Add(_pumpOneSpm[i]);
spm.Add(_pumpTwoSpm[i]);
}
}
}
return _dailyProjectMaxSpm = Math.Round(spm.Max(), 2, MidpointRounding.AwayFromZero);
}
I'm trying to make the method look a little less unwieldy. I had tried:
public double CalculateDailyProjectMaxPumpSpm(DateTime date, string start = null, string end = null)
{
Log("Calculating Daily Pump stroke Max...");
var spm = start == null ? _pumpOneSpm.Concat(_pumpTwoSpm).Where((t, i) => _date[i].Equals(date)).ToList()
: _pumpOneSpm.Concat(_pumpTwoSpm).Where((t, i) => _date[i].Equals(date) &&
DateTime.Compare(_time[i], DateTime.Parse(start)) > 0 &&
DateTime.Compare(_time[i], DateTime.Parse(end)) < 0).ToList();
_dailyProjectMaxSpm = Math.Round(spm.Max(), 2, MidpointRounding.AwayFromZero);
return _dailyProjectMaxSpm;
}
But when I ran the program I got an Index out of range. Must be non-negative and less than the size of the collection. Parameter name: index
error. Now, I couldn't care less what order the elements are added to the new list, just so long as if the conditions are met, they are added. Could anyone help me out with the error? Thanks.
UPDATE
_date
is a list of dates pulled from a database, and _time
is a list of timestamps pulled from the same database. All variables with the _
is a list pulled from a database. The Count
of each list will always be equal to the Count
of each other list.
Upvotes: 0
Views: 938
Reputation: 2521
Like sil said, you're concatenating the two lists, resulting in a list with a larger index range. How about this solution, which uses Enumerable.Range() to produce the indexes, then uses a combined version of your two predicates to filter, and finally flattens the list with SelectMany():
public double CalculateDailyProjectMaxPumpSpm(DateTime date, string start = null, string end = null)
{
Log("Calculating Daily Pump stroke Max...");
var spm = Enumerable
.Range(0, _pumpOneSpm.Count)
.Where(x => _date[x].Equals(date) &&
(start == null ||
(DateTime.Compare(_time[x], DateTime.Parse(start)) > 0 &&
DateTime.Compare(_time[x], DateTime.Parse(end)) < 0)))
.SelectMany(x => new [] { _pumpOneSpm[x], _pumpTwoSpm[x] });
return _dailyProjectMaxSpm = Math.Round(spm.Max(), 2, MidpointRounding.AwayFromZero);
}
Upvotes: 1
Reputation: 62484
In original method i
is in range from 0
to _pumpOneSpm.Count
but now from 0
to
_pumpOneSpm.Count + _pumpTwoSpm.Count
Following results in a list of _pumpOneSpm.Count + _pumpTwoSpm.Count
items:
_pumpOneSpm.Concat(_pumpTwoSpm).Where((t, i) => _date[i]
And I cannot see LINQ analogue which would be more clear than your first method example using for
loops.
Upvotes: 1