Created
August 14, 2013 15:53
-
-
Save bradwilson/6232391 to your computer and use it in GitHub Desktop.
IIndexedEnumerable (a non-grouped replacement for ILookup)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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