65.9K
CodeProject is changing. Read more.
Home

Modular IEnumerable Extensions

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.75/5 (4 votes)

Apr 8, 2014

CPOL
viewsIcon

15145

This tip describes an IEnumerable extension method that allows you to select an item modulo Count()

Introduction

This tip describes an IEnumerable extension method that allows you to select an item at its index modulo Count().

Using the Code

Given an object enumerable that implements IEnumerable<T>, you can use the following extension method ElementAtModCount to select an item from this object in the sense that:

enumerable.ElementAtModCount(i) = enumerable.ElementAtModCount(i mod Count)  

This extension method is given as follows:

using System.Collections.Generic;
using System.Linq;

namespace CodeProject.Articles.EnumerableExtensions
{
    public static class EnumerableExtensions
    {
        /// <summary>
        /// Returns the element of an object that implements
        /// IEnumerable at the index modulo the total number of 
        /// elements in that object.
        /// </summary>
        /// <typeparam name="T">Type T</typeparam>
        /// <param name="enumerable">An IEnumerable</param>
        /// <param name="index">The index of the item to get</param>
        /// <returns></returns>
        public static T ElementAtModCount<T>(this IEnumerable<T> enumerable, int index)
        {
            // In general, an object implementing IEnumerable does not have the 
            // Count property (O(1)), so it is expensive to call .Count() (O(n)). 
            // So we set it here, just in case...     
            var count = enumerable.Count();

            var indexModCount = ((index % count) + count) % count;

            // Again, in general this is quite expensive (O(n)). But
            // like above, if an object implements IEnumerable, and has the [] indexer
            // then this is O(1)
            return enumerable.ElementAt(indexModCount);
        }

    }
}

An example of how to use this is given as follows:

using CodeProject.Articles.EnumerableExtensions;
using System;
using System.Collections.Generic;

namespace CodeProject
{
    class Program
    {
        static void Main(string[] args)
        {
            var list =
                new List<string>() 
                { "Monday", "Tuesday", "Wednesday", "Thursday", 
                  "Friday", "Saturday", "Sunday" };

            // The answer's Tuesday
            Console.WriteLine(string.Format(
                "It is Monday today, and in 365 days it will be {0}",
                list.ElementAtModCount(365)));

            // The answer's Friday
            Console.WriteLine(string.Format(
               "It is Monday today, and three days ago it was {0}",
               list.ElementAtModCount(-3)));

            Console.ReadLine();
        }
    }
}