Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 105 additions & 0 deletions ShittyLINQ/ToLookup.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
using System;
using System.Collections.Generic;

namespace ShittyLINQ
{
public static partial class Extensions
{
/// <summary>
/// Creates a lookup from an IEnumerable
/// </summary>
/// <param name="source">Set of elements to be converted to lookup</param>
/// <param name="keySelector">Key selector to determine the key of the lookup</param>
/// <typeparam name="TSource">Source type</typeparam>
/// <typeparam name="TKey">Key type</typeparam>
/// <returns>A lookup made from source</returns>
/// <exception cref="ArgumentNullException">If source, keySelector or element Selector is null</exception>
public static Dictionary<TKey, IEnumerable<TSource>> ToLookup<TSource, TKey>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector)
{
return ToLookup(source, keySelector, t => t, EqualityComparer<TKey>.Default);
}

/// <summary>
/// Creates a lookup from an IEnumerable
/// </summary>
/// <param name="source">Set of elements to be converted to lookup</param>
/// <param name="keySelector">Key selector to determine the key of the lookup</param>
/// <param name="elementSelector">Element selector to determine the value of the lookup</param>
/// <typeparam name="TSource">Source type</typeparam>
/// <typeparam name="TKey">Key type</typeparam>
/// <typeparam name="TElement">Value type</typeparam>
/// <returns>A lookup made from source</returns>
/// <exception cref="ArgumentNullException">If source, keySelector or element Selector is null</exception>
public static Dictionary<TKey, IEnumerable<TElement>> ToLookup<TSource, TKey, TElement>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector,
Func<TSource, TElement> elementSelector)
{
return source.ToLookup(keySelector, elementSelector, EqualityComparer<TKey>.Default);
}

/// <summary>
/// Creates a lookup from an IEnumerable
/// </summary>
/// <param name="source">Set of elements to be converted to lookup</param>
/// <param name="keySelector">Key selector to determine the key of the lookup</param>
/// <param name="comparer">Comparer to be used to determine equality between elements</param>
/// <typeparam name="TSource">Source type</typeparam>
/// <typeparam name="TKey">Key type</typeparam>
/// <returns>A lookup made from source</returns>
/// <exception cref="ArgumentNullException">If source, keySelector or element Selector is null</exception>
public static Dictionary<TKey, IEnumerable<TSource>> ToLookup<TSource, TKey>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector,
IEqualityComparer<TKey> comparer)
{
return ToLookup(source, keySelector, t => t, comparer);
}

/// <summary>
/// Creates a lookup from an IEnumerable
/// </summary>
/// <param name="source">Set of elements to be converted to lookup</param>
/// <param name="keySelector">Key selector to determine the key of the lookup</param>
/// <param name="elementSelector">Element selector to determine the value of the lookup</param>
/// <param name="comparer">Comparer to be used to determine equality between elements</param>
/// <typeparam name="TSource">Source type</typeparam>
/// <typeparam name="TKey">Key type</typeparam>
/// <typeparam name="TElement">Value type</typeparam>
/// <returns>A lookup made from source</returns>
/// <exception cref="ArgumentNullException">If source, keySelector or element Selector is null</exception>
public static Dictionary<TKey, IEnumerable<TElement>> ToLookup<TSource, TKey, TElement>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector,
Func<TSource, TElement> elementSelector,
IEqualityComparer<TKey> comparer)
{
if (source == null || keySelector == null || elementSelector == null) throw new ArgumentNullException();

List<TElement> tempList;
IEnumerable<TElement> existingValues;

Dictionary<TKey, IEnumerable<TElement>> ret = new Dictionary<TKey, IEnumerable<TElement>>(comparer ?? EqualityComparer<TKey>.Default);
foreach (TSource item in source)
{
existingValues = ret.GetValueOrDefault(keySelector(item));
if (existingValues == null)
{
tempList = new List<TElement>();
}
else
{
tempList = existingValues.ToList();
ret.Remove(keySelector(item));
}
tempList.Add(elementSelector(item));
ret.Add(keySelector(item), tempList);

}
return ret;
}
}

}
42 changes: 42 additions & 0 deletions ShittyLinqTests/ToLookupTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using ShittyLINQ;
using ShittyTests.TestHelpers;

namespace ShittyTests
{
[TestClass]
public class ToLookupTests
{
[TestMethod]
public void ToLookup_Numbers()
{
IEnumerable<int> numbers = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };

var result = numbers.ToLookup(x => x, x => true);

Assert.AreEqual(result.Count, 9);

foreach (int number in numbers)
{
Assert.IsTrue(result.ContainsKey(number));
}
}

[TestMethod]
public void ToLookup_Person()
{
var adam = new Person("Adam", 20, "Arquitech", "Amber");
var brian = new Person("Brian", 45, "Arquitech", "Blue");
var charles = new Person("Charles", 33, "Arquitech", "Cyan");
var dani = new Person("Dani", 33, "Developer", "Deep Purple");

IEnumerable<Person> people = new[] { adam, brian, charles, dani };

var result = people.ToLookup(person => person.Age);

Assert.AreEqual(result.TryGetValue(brian.Age, out var expectedBrian), true);
Assert.IsNotNull(expectedBrian);
}
}
}