Skip to content

Instantly share code, notes, and snippets.

@bradwilson
Created August 14, 2013 15:53
Show Gist options
  • Select an option

  • Save bradwilson/6232391 to your computer and use it in GitHub Desktop.

Select an option

Save bradwilson/6232391 to your computer and use it in GitHub Desktop.
IIndexedEnumerable (a non-grouped replacement for ILookup)
using System;
using System.Collections.Generic;
using System.Linq;
public interface IIndexedEnumerable<TKey, TValue>
{
TValue this[TKey key] { get; }
int Count { get; }
bool TryGetValue(TKey key, out TValue value);
}
public static class IndexedEnumerableExtensions
{
public static IIndexedEnumerable<TKey, TValue> ToIndexedEnumerable<TKey, TValue>(this IDictionary<TKey, TValue> dictionary)
{
return new IndexedEnumerable<TKey, TValue>(dictionary.ToTuple, () => dictionary.Keys.Count);
}
public static IIndexedEnumerable<TKey, TValue> ToIndexedEnumerable<TSource, TKey, TValue>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TValue> elementSelector)
{
return source.ToIndexedEnumerable(keySelector, elementSelector, new DefaultComparer<TKey>());
}
public static IIndexedEnumerable<TKey, TValue> ToIndexedEnumerable<TSource, TKey, TValue>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TValue> elementSelector, IEqualityComparer<TKey> comparer)
{
return new IndexedEnumerable<TKey, TValue>(key => source.ToTuple(key, keySelector, elementSelector, comparer), () => source.Count());
}
private static Tuple<bool, TValue> ToTuple<TSource, TKey, TValue>(this IEnumerable<TSource> source, TKey key, Func<TSource, TKey> keySelector, Func<TSource, TValue> elementSelector, IEqualityComparer<TKey> comparer)
{
var values = source.Where(sourceItem => comparer.Equals(key, keySelector(sourceItem)))
.Take(1)
.ToList();
if (values.Count > 0)
return Tuple.Create(true, elementSelector(values[0]));
return Tuple.Create(false, default(TValue));
}
private static Tuple<bool, TValue> ToTuple<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key)
{
TValue result;
bool found = dictionary.TryGetValue(key, out result);
return Tuple.Create(found, result);
}
class DefaultComparer<T> : IEqualityComparer<T>
{
public bool Equals(T x, T y)
{
return Equals(x, y);
}
public int GetHashCode(T obj)
{
return obj.GetHashCode();
}
}
class IndexedEnumerable<TKey, TValue> : IIndexedEnumerable<TKey, TValue>
{
private readonly Lazy<int> count;
private readonly Func<TKey, Tuple<bool, TValue>> lookup;
public IndexedEnumerable(Func<TKey, Tuple<bool, TValue>> lookup, Func<int> countThunk)
{
this.lookup = lookup;
count = new Lazy<int>(countThunk);
}
public TValue this[TKey key]
{
get
{
TValue result;
if (TryGetValue(key, out result))
return result;
throw new KeyNotFoundException();
}
}
public int Count { get { return count.Value; } }
public bool TryGetValue(TKey key, out TValue value)
{
var tuple = lookup(key);
value = tuple.Item2;
return tuple.Item1;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment