-1

I am looking to return a List or Dictionary Value, in order, but at a different index in the list or dictionary at different times.

For example, if I have the following Dictionary:

public static readonly Dictionary<int, int> DaysInTheMonth = new Dictionary<int, int>
{
    { 1, 31 }, // Jan
    { 2, 28 }, // Feb
    { 3, 31 }, // Mar
    { 4, 30 }, // Apr
    { 5, 31 }, // May
    { 6, 30 }, // Jun
    { 7, 31 }, // Jul
    { 8, 31 }, // Aug
    { 9, 30 }, // Sep
    { 10, 31 }, // Oct
    { 11, 30 }, // Nov
    { 12, 31 } // Dec
};

Where:

DaysInTheMonth[1]

Returns:

31

I may instead need to start at 7, and look all the way through to 5 again, in a Circular fashion.

for (int i = 7; i <= DaysInTheMonth.Count; i++)
{
    Days += DaysInTheMonth[i];
}

Of course, I am missing the indexes 1 through 5 with this loop!

Using this ugly code:

private static int GetTotalDays(int startMonth, int endMonth)
{

    int Days = 0;
    int Index = startMonth;
    bool Oneshot = (startMonth >= endMonth ? false : true);

    for (int i = 1; i <= DaysInTheMonth.Count; i++) 
    {

        Days += DaysInTheMonth[Index];

        Index++;

        if (Index >= DaysInTheMonth.Count)
        {
            Oneshot = true;
            Index = 1;
        }

        if(Index > endMonth && Oneshot) break;
    }

return Days;
}

There must be a better way!

I found this link that is similar: Looking for circular list solution however it does not allow for Indexing and changing as I require.

Instead of having a lot of if operators, moving Circular and an Indexer that is always needing to be checked.

There must be a better way!

EDIT: OnRequestForClarity.

The Gregorian Calendar is exactly 365.25 days, thus every 4 Years we have a Leap Year: 4 x 0.25 = 1 Day, so February becomes 29 Days for this Leap Year and back to 28 every other year! Every Month has a different number of Days, for example, 365.25 / 12 = 30.4375 days, however, not all months have this number of days! The number of Days is set in the Dictionary I provided above. Thus if one counts Days, as in a TimeSpan, this is fine if one is not looking at the months, but if one wants to count months, then one needs to Equate the correct Days to the Specific Months! Right? So Order of Counting is important!

Count from Month 1 to Month 3, do you get the same answer if you count from Month 6 to Month 8? No!

Order is Important!

Rusty Nail
  • 2,692
  • 3
  • 34
  • 55
  • 2
    I'm assuming this is not the actual scenario you're trying to solve. If it is, it seems like you could do 365 - DaysInTheMonth[month]. If you have a different scenario where you need to iterate in a circular manner you could use a modulus on the index. i % DaysInTheMonth.Count where i == 7 would return 7. Where i == 12, i % DaysInTheMonth.Count would be 0. – emagers Jul 02 '22 at 04:06
  • @emagers it is one and the same. Let me add another example. – Rusty Nail Jul 02 '22 at 04:08
  • @emagers, no, one can not use days as in 365, if the order is out by a fraction, the days returned by the method will be incorrect. The approach does not work, I have tried. – Rusty Nail Jul 02 '22 at 05:24
  • Does your current implementation work for you? It seems to me that the `if (Index >= DaysInTheMonth.Count)` statement will ensure that December is _never_ included in the total days count, except in the case where `startMonth == 12`. – Astrid E. Jul 02 '22 at 05:55
  • _Count from Month 1 to Month 3, do you get the same answer if you count from Month 6 to Month 8? No!_ I agree, but here, you are emphasizing the importance of the _selection_ of months, not the _order_ of months. If I count _month 1, month 2, month 3_ or _month 2, month 3, month 1_, would those two counts result in the same answer? Yes. – Astrid E. Jul 03 '22 at 05:59

1 Answers1

0

Given your example scenario (returning a sum of Values), it seems to me like you do not need to actually get each Value in order; what is important is simply getting the Values for the correct subset of months. Also, you are fetching each Value based on a Key that exists in the dictionary, not based on an index.

If this is the case, you could first filter out the correct subset of months, and then iterate over that subset to retrieve each respective Value.

The filtering of months will look different if endMonth >= startMonth than if endMonth < startMonth. You may utilize the method .Where() from the namespace System.Linq to do the filtering accordingly.

A possible implementation may look like the following:

//DaysInTheMonth is a Dictionary<int, int>

private static int GetTotalDays(int startMonth, int endMonth)
{
    var months = DaysInTheMonth.Select(entry => entry.Key);

    if (endMonth >= startMonth)
    {
        months = months
            .Where(m => m >= startMonth && m <= endMonth);
    }
    else
    {
        months = months
            .Where(m => m >= startMonth || m <= endMonth);
    }

    int days = 0;

    foreach (var month in months)
    {
        days += DaysInTheMonth[month];
    }

    return days;
}

For startMonth = 7 and endMonth = 5, this will calculate the sum of days in this order of months: 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 12 rather than 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5

Example fiddle here.

Astrid E.
  • 2,280
  • 2
  • 6
  • 17
  • Nice, but I believe the order of the counting here is going to be an issue? Yes? worth testing, thank you, but I believe this has issues I have already faced. – Rusty Nail Jul 02 '22 at 05:42
  • It is still not clear to me why _order_ is important to you; you are getting the values from your dictionary by using each entry's `Key`, not an index. Also, you simply need to sum total days, you are not performing a specific action after getting the value for a given month. Order seems (to me) to be irrelevant for this. – Astrid E. Jul 02 '22 at 05:48
  • @RustyNail If the circular looping actually is important, please elaborate _why_ in your original question. When looking at your original code, it is _not_ clear why the order of months should have any importance, as long as you ensure to filter out the _relevant_ months. – Astrid E. Jul 02 '22 at 05:58
  • Clarity added as requested. – Rusty Nail Jul 02 '22 at 23:59
  • @RustyNail I have updated one line in my suggestion code (replaced `var months = DaysInTheMonth.Keys;` with `var months = DaysInTheMonth.Select(entry => entry.Key);`) and provided a fiddle example. The clarity you provided did not help me understand your problem with my suggested approach. Perhaps if you share what your expected output actually is for a certain pair of `startMonth` and `endMonth`, which this approach does not give you, it may help my understanding. – Astrid E. Jul 03 '22 at 06:20
  • I know that my approach does not account for leap years, but your original post also does not account for that, and leap years do not seem to be part of your original question at all. – Astrid E. Jul 03 '22 at 06:21