diff --git a/ShittyLINQ/GroupBy.cs b/ShittyLINQ/GroupBy.cs
new file mode 100644
index 0000000..0ab4165
--- /dev/null
+++ b/ShittyLINQ/GroupBy.cs
@@ -0,0 +1,180 @@
+using System;
+using System.Collections.Generic;
+
+namespace ShittyLINQ
+{
+ public static partial class Extensions
+ {
+ ///
+ /// Groups the elements of a sequence.
+ ///
+ /// An IEnumerable whose elements to group.
+ /// A function to extract the key for each element.
+ /// Source type
+ /// Key type
+ /// A collection of elements where each element represents a projection over a group and its key.
+ /// If source, keySelector or element Selector is null
+ public static Dictionary> GroupBy(
+ this IEnumerable source,
+ Func keySelector)
+ {
+ return GroupBy(source, keySelector, t => t, EqualityComparer.Default);
+ }
+
+
+ ///
+ /// Groups the elements of a sequence.
+ ///
+ /// An IEnumerable whose elements to group.
+ /// A function to extract the key for each element.
+ /// An IEqualityComparer to compare keys with.
+ /// Source type
+ /// Key type
+ /// A collection of elements where each element represents a projection over a group and its key.
+ /// If source, keySelector or element Selector is null
+ public static Dictionary> GroupBy(
+ this IEnumerable source,
+ Func keySelector,
+ IEqualityComparer comparer)
+ {
+ return GroupBy(source, keySelector, t => t, comparer);
+ }
+
+
+ ///
+ /// Groups the elements of a sequence.
+ ///
+ /// An IEnumerable whose elements to group.
+ /// A function to extract the key for each element.
+ /// A function to map each source element to an element in an IGrouping
+ /// Source type
+ /// Key type
+ /// Value type
+ /// A collection of elements where each element represents a projection over a group and its key.
+ /// If source, keySelector or element Selector is null
+ public static Dictionary> GroupBy(
+ this IEnumerable source,
+ Func keySelector,
+ Func elementSelector)
+ {
+ return GroupBy(source, keySelector, elementSelector, EqualityComparer.Default);
+ }
+
+
+ ///
+ /// Groups the elements of a sequence.
+ ///
+ /// An IEnumerable whose elements to group.
+ /// A function to extract the key for each element.
+ /// A function to map each source element to an element in an IGrouping
+ /// Source type
+ /// Key type
+ /// Value type
+ /// An IEqualityComparer to compare keys with.
+ /// A collection of elements where each element represents a projection over a group and its key.
+ /// If source, keySelector or element Selector is null
+ public static Dictionary> GroupBy(
+ this IEnumerable source,
+ Func keySelector,
+ Func elementSelector,
+ IEqualityComparer comparer)
+ {
+ if (source == null || keySelector == null || elementSelector == null)
+ throw new ArgumentNullException();
+
+ Dictionary> res = new Dictionary>(comparer ?? EqualityComparer.Default);
+
+ foreach (TSource item in source)
+ {
+ var subset = source.Where(b => keySelector(b).Equals(keySelector(item))).Select(a => elementSelector(a)).ToList();
+ if (!res.ContainsKey(keySelector(item)))
+ {
+ res.Add(keySelector(item), subset);
+ }
+ }
+ return res;
+ }
+
+ ///
+ /// Groups the elements of a sequence.
+ ///
+ /// An IEnumerable whose elements to group.
+ /// A function to extract the key for each element.
+ /// A function to create a result value from each group.
+ /// An IEqualityComparer to compare keys with.
+ /// Source type
+ /// Key type
+ /// The type of the result value returned by resultSelector
+ /// A collection of elements of type TResult where each element represents a projection over a group and its key.
+ /// If source, keySelector or element Selector is null
+ public static IEnumerable GroupBy(
+ this IEnumerable source,
+ Func keySelector,
+ Func, TResult> resultSelector)
+ {
+ return GroupBy(source, keySelector, t => t, resultSelector, EqualityComparer.Default);
+ }
+
+
+ ///
+ /// Groups the elements of a sequence.
+ ///
+ /// An IEnumerable whose elements to group.
+ /// A function to extract the key for each element.
+ /// A function to create a result value from each group.
+ /// An IEqualityComparer to compare keys with.
+ /// Source type
+ /// Key type
+ /// The type of the result value returned by resultSelector
+ /// A collection of elements of type TResult where each element represents a projection over a group and its key.
+ /// If source, keySelector or element Selector is null
+ public static IEnumerable GroupBy(
+ this IEnumerable source,
+ Func keySelector,
+ Func, TResult> resultSelector,
+ IEqualityComparer comparer)
+ {
+ return GroupBy(source, keySelector, t => t, resultSelector, comparer);
+ }
+
+
+
+
+ ///
+ /// Groups the elements of a sequence.
+ ///
+ /// An IEnumerable whose elements to group.
+ /// A function to extract the key for each element.
+ /// A function to map each source element to an element in an IGrouping
+ /// A function to create a result value from each group.
+ /// An IEqualityComparer to compare keys with.
+ /// Source type
+ /// Key type
+ /// Value type
+ /// The type of the result value returned by resultSelector
+ /// A collection of elements of type TResult where each element represents a projection over a group and its key.
+ /// If source, keySelector or element Selector is null
+ public static IEnumerable GroupBy(
+ IEnumerable source,
+ Func keySelector,
+ Func elementSelector,
+ Func, TResult> resultSelector,
+ IEqualityComparer comparer)
+ {
+ if (source == null || keySelector == null || elementSelector == null || resultSelector == null || comparer == null)
+ throw new ArgumentNullException();
+
+ List res = new List();
+
+ foreach (TSource item in source)
+ {
+ var subset = source.Where(b => keySelector(b).Equals(keySelector(item))).Select(a => elementSelector(a)).ToList();
+ if (!res.Contains(resultSelector(keySelector(item), subset)))
+ {
+ res.Add(resultSelector(keySelector(item), subset));
+ }
+ }
+ return res;
+ }
+ }
+}
diff --git a/ShittyLinqTests/GroupByTests.cs b/ShittyLinqTests/GroupByTests.cs
new file mode 100644
index 0000000..2eef660
--- /dev/null
+++ b/ShittyLinqTests/GroupByTests.cs
@@ -0,0 +1,47 @@
+using System.Collections.Generic;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using ShittyLINQ;
+using ShittyTests.TestHelpers;
+
+namespace ShittyTests
+{
+ [TestClass]
+ public class GroupByTests
+ {
+
+ [TestMethod]
+ public void GroupBy_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 people = new[] { adam, brian, charles, dani };
+
+ var result = people.GroupBy(person => person.Age);
+
+ Assert.AreEqual(result.Count, 3);
+ Assert.AreEqual(result.GetValueOrDefault(20).First(), adam);
+ }
+
+ [TestMethod]
+ public void GroupBy_Person_WithResultSelector()
+ {
+ 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 people = new[] { adam, brian, charles, dani };
+
+ var result = people.GroupBy(person => person.Age,
+ (baseAge, ages) => new
+ {
+ Key = baseAge,
+ Count = (int)ages.Count()
+ });
+
+ Assert.AreEqual(result.ToList().Count, 3);
+ Assert.AreEqual(result.ToList().Max(a => a.Count), 2);
+ }
+ }
+}
\ No newline at end of file