Modular IEnumerable Extensions
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();
}
}
}