Skip to content

Instantly share code, notes, and snippets.

@ckpearson
Last active August 29, 2015 14:06
Show Gist options
  • Save ckpearson/9ce181670c2f37846fd7 to your computer and use it in GitHub Desktop.
Save ckpearson/9ce181670c2f37846fd7 to your computer and use it in GitHub Desktop.
Hierarchise a collection
/// <summary>
/// Takes an enumerable of items and builds a hierarchy from two properties present on the item
/// </summary>
/// <typeparam name="TOuter">The type of the outer key</typeparam>
/// <typeparam name="TInner">The type of the inner key</typeparam>
/// <typeparam name="TValue">The type of the item being processed</typeparam>
/// <param name="items">The enumerable to process</param>
/// <param name="outerSelector">Function for accessing the outer key</param>
/// <param name="innerSelector">Function for accessing the inner key</param>
public static Dictionary<TOuter, Dictionary<TInner, TValue>> Hierarchise<TOuter, TInner, TValue>(this IEnumerable<TValue> items,
Func<TValue, TOuter> outerSelector,
Func<TValue, TInner> innerSelector)
{
return items.GroupBy(outerSelector)
.Select(og => new KeyValuePair<TOuter, IEnumerable<KeyValuePair<TInner, TValue>>>(
og.Key, og.Select(gi => new KeyValuePair<TInner, TValue>(innerSelector(gi), gi))))
.ToDictionary(kvp => kvp.Key, kvp => kvp.Value.ToDictionary(k => k.Key, k => k.Value));
}
@ckpearson
Copy link
Author

Using it is as simple as: Customers.Hierarchise(c => c.LastName, c => c.FirstName)

Just watch out for colliding keys as they're not dealt with.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment