PiousVenom
PiousVenom

Reputation: 6908

Index out of range error

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

Answers (2)

Risky Martin
Risky Martin

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

sll
sll

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

Related Questions