Created
March 20, 2013 21:30
-
-
Save ldiego08/5208654 to your computer and use it in GitHub Desktop.
Sample implementation of some LINQ methods.
This file contains 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; | |
namespace Codenough.Demos.MapReduce | |
{ | |
public static class ListQuery | |
{ | |
public delegate bool Comparator<TSource>(TSource current, TSource target); | |
public delegate TAccumulate Aggregator<TSource, TAccumulate>(TSource current, TAccumulate value); | |
public static IEnumerable<TResult> Select<TSource, TResult>(IEnumerable<TSource> source, Func<TSource, TResult> selector) | |
{ | |
if (source == null) | |
{ | |
throw new ArgumentNullException("source"); | |
} | |
if (selector == null) | |
{ | |
throw new ArgumentNullException("selector"); | |
} | |
using (var iterator = source.GetEnumerator()) | |
{ | |
if (!iterator.MoveNext()) | |
{ | |
throw new InvalidOperationException("Source enumerator contains no elements."); | |
} | |
do | |
{ | |
var currentElement = iterator.Current; | |
yield return selector(currentElement); | |
} while (iterator.MoveNext()); | |
} | |
} | |
public static IEnumerable<TSource> Where<TSource>(IEnumerable<TSource> source, Predicate<TSource> predicate) | |
{ | |
if (source == null) | |
{ | |
throw new ArgumentNullException("source"); | |
} | |
if (predicate == null) | |
{ | |
throw new ArgumentNullException("predicate"); | |
} | |
using (var iterator = source.GetEnumerator()) | |
{ | |
if (!iterator.MoveNext()) | |
{ | |
throw new InvalidOperationException("Source enumerator contains no elements."); | |
} | |
do | |
{ | |
var currentElement = iterator.Current; | |
if (predicate(currentElement)) | |
{ | |
yield return currentElement; | |
} | |
} while (iterator.MoveNext()); | |
} | |
} | |
public static TSource Where<TSource>(IEnumerable<TSource> source, Comparator<TSource> comparator) | |
{ | |
if (source == null) | |
{ | |
throw new ArgumentNullException("source"); | |
} | |
if (comparator == null) | |
{ | |
throw new ArgumentNullException("comparator"); | |
} | |
using (var iterator = source.GetEnumerator()) | |
{ | |
if (!iterator.MoveNext()) | |
{ | |
throw new InvalidOperationException("Source enumerator contains no elements."); | |
} | |
var resultElement = iterator.Current; | |
do | |
{ | |
var currentElement = iterator.Current; | |
if (comparator(currentElement, resultElement)) | |
{ | |
resultElement = currentElement; | |
} | |
} while (iterator.MoveNext()); | |
return resultElement; | |
} | |
} | |
public static TAccumulate Aggregate<TSource, TAccumulate>(IEnumerable<TSource> source, TAccumulate seed, Aggregator<TSource, TAccumulate> aggregator) | |
{ | |
return Aggregate(source, seed, x => x, aggregator); | |
} | |
public static TResult Aggregate<TSource, TAccumulate, TResult>(IEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TResult> selector, Aggregator<TSource, TAccumulate> aggregator) | |
{ | |
if (source == null) | |
{ | |
throw new ArgumentNullException("source"); | |
} | |
if (aggregator == null) | |
{ | |
throw new ArgumentNullException("aggregator"); | |
} | |
if (selector == null) | |
{ | |
throw new ArgumentNullException("selector"); | |
} | |
using (var iterator = source.GetEnumerator()) | |
{ | |
if (!iterator.MoveNext()) | |
{ | |
throw new InvalidOperationException("Source enumerator contains no elements."); | |
} | |
TAccumulate accumulate = seed; | |
do | |
{ | |
var currentElement = iterator.Current; | |
accumulate = aggregator(currentElement, accumulate); | |
} while (iterator.MoveNext()); | |
return selector(accumulate); | |
} | |
} | |
public static IEnumerable<TSource> Order<TSource, TKey>(IEnumerable<TSource> source, Func<TSource, TKey> keySelector) | |
where TKey : IComparable<TKey> | |
{ | |
if (source == null) | |
{ | |
throw new ArgumentNullException("source"); | |
} | |
if (keySelector == null) | |
{ | |
throw new ArgumentNullException("keySelector"); | |
} | |
var sourceList = new List<TSource>(source); | |
if (sourceList.Count == 0) | |
{ | |
throw new InvalidOperationException("Source sequence is empty."); | |
} | |
for (int iterator = 0; iterator < sourceList.Count; iterator++) | |
{ | |
for (int index = 0; index < sourceList.Count - 1; index++) | |
{ | |
var currentItem = sourceList[index]; | |
var currentValue = keySelector(currentItem); | |
var nextItem = sourceList[index + 1]; | |
var nextValue = keySelector(nextItem); | |
if (currentValue.CompareTo(nextValue) > 0) | |
{ | |
sourceList.Remove(nextItem); | |
sourceList.Insert(index, nextItem); | |
} | |
} | |
} | |
return sourceList; | |
} | |
public static IDictionary<TKey, IList<TSource>> Group<TKey, TSource>(IEnumerable<TSource> source, Func<TSource, TKey> keySelector) | |
{ | |
if (source == null) | |
{ | |
throw new ArgumentNullException("source"); | |
} | |
if (keySelector == null) | |
{ | |
throw new ArgumentNullException("keySelector"); | |
} | |
using (var iterator = source.GetEnumerator()) | |
{ | |
if (!iterator.MoveNext()) | |
{ | |
throw new InvalidOperationException("Source enumerator contains no elements."); | |
} | |
var groups = new Dictionary<TKey, IList<TSource>>(); | |
do | |
{ | |
var currentElement = iterator.Current; | |
var key = keySelector(currentElement); | |
if (groups.ContainsKey(key)) | |
{ | |
groups[key].Add(currentElement); | |
} | |
else | |
{ | |
groups.Add(key, new List<TSource>() { currentElement }); | |
} | |
} while (iterator.MoveNext()); | |
return groups; | |
} | |
} | |
} | |
} |
This file contains 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 Codenough.Demos.MapReduce.Data; | |
using Codenough.Demos.MapReduce.Data.Model; | |
using System; | |
using System.Linq; | |
namespace Codenough.Demos.MapReduce | |
{ | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
var dataSource = new DataSource(); | |
// Ex. 1: Print all car brands. | |
var carBrands = ListQuery | |
.Aggregate(dataSource.Cars, String.Empty, JoinCarBrand) | |
.Remove(0, 2); | |
Console.WriteLine("Car brands:" + carBrands); | |
Console.WriteLine(); | |
// Ex. 2: Select all Toyota sales. | |
var toyotaSales = ListQuery.Where(dataSource.Sales, sale => sale.Car.Brand == "Toyota"); | |
Console.WriteLine("Total Toyota sales: " + toyotaSales.Count()); | |
Console.WriteLine(); | |
// Ex. 3: Find buys of youngest person. | |
var youngerPerson = ListQuery.Where(dataSource.Persons, (cur, target) => cur.Age < target.Age); | |
var youngerPersonBuys = ListQuery.Where(dataSource.Sales, sale => sale.Buyer == youngerPerson); | |
Console.WriteLine(String.Format("The younger person is {0} {1} with a total of {2} cars bought.", youngerPerson.FirstName, youngerPerson.LastName, youngerPersonBuys.Count())); | |
Console.WriteLine(); | |
// Ex. 4: Find most expensive sale. | |
var mostExpensiveSale = ListQuery.Where(dataSource.Sales, (cur, target) => cur.Cost > target.Cost); | |
Console.WriteLine(String.Format("Most expensive sale was for {0:c}", mostExpensiveSale.Cost)); | |
Console.WriteLine(); | |
// Ex. 5: Sum sale costs where both buyer and seller are male. | |
var maleSales = ListQuery.Where(dataSource.Sales, sale => sale.Seller.Gender == "Male" && sale.Buyer.Gender == "Male"); | |
var maleSalesCost = ListQuery.Aggregate(maleSales, 0.0, (sale, total) => total + sale.Cost); | |
Console.WriteLine(String.Format("Total cost of sales where both buyer and seller are male: {0:c}", maleSalesCost)); | |
Console.WriteLine(); | |
// Ex. 6: Find age of the youngest person that has bought more than $40,000. | |
var youngerPersonWithHighestSale = ListQuery.Where(dataSource.Sales, (cur, target) => cur.Cost > 40000 && cur.Buyer.Age < target.Buyer.Age); | |
Console.WriteLine(String.Format("Youngest person with a buy for more than $40,000: {0} {1}", youngerPersonWithHighestSale.Buyer.FirstName, youngerPersonWithHighestSale.Buyer.LastName)); | |
Console.WriteLine(); | |
// Ex. 7: Sort sales by cost. | |
var sortedSalesByCost = ListQuery.Order(dataSource.Sales, sale => sale.Cost); | |
Console.WriteLine("Sales sorted by cost:"); | |
foreach (var sale in sortedSalesByCost) | |
{ | |
Console.WriteLine(String.Format("\t{0} = {1:c}", sale.Car.Brand, sale.Cost)); | |
} | |
Console.WriteLine(); | |
// Ex. 8: Select cars original costs. | |
var carCosts = ListQuery.Select(dataSource.Cars, car => car.OriginalValue); | |
Console.WriteLine("Original car costs:"); | |
foreach (var carCost in carCosts) | |
{ | |
Console.WriteLine("\t" + carCost); | |
} | |
Console.WriteLine(); | |
// Ex. 9: Index cars by brand. | |
var salesGroupedByCarBrand = ListQuery.Group(dataSource.Sales, sale => sale.Car.Brand); | |
Console.WriteLine("Cars grouped by brand:"); | |
foreach (var saleGroup in salesGroupedByCarBrand) | |
{ | |
Console.WriteLine(String.Format("\t{0} = {1}", saleGroup.Key, saleGroup.Value.Count)); | |
} | |
Console.WriteLine(); | |
// Ex. 10: Group sales by buyers and sellers. | |
var salesGroupedByBuyerAndSeller = ListQuery.Group(dataSource.Sales, sale => new { sale.Buyer, sale.Seller }); | |
Console.WriteLine("Sales grouped by buyer and seller:"); | |
foreach (var saleGroup in salesGroupedByBuyerAndSeller) | |
{ | |
Console.WriteLine(String.Format("\t{0}/{1} = {2}", saleGroup.Key.Buyer.FirstName, saleGroup.Key.Seller.FirstName, saleGroup.Value.Count)); | |
} | |
Console.WriteLine(); | |
// Ex. 11: Find most sold car. | |
var salesGroupedByCar = ListQuery.Group(dataSource.Sales, sale => sale.Car); | |
var mostSoldCar = ListQuery.Where(salesGroupedByCar, (cur, target) => cur.Value.Count > target.Value.Count).Key; | |
Console.WriteLine(String.Format("Most sold car brand: {0}", mostSoldCar.Brand)); | |
Console.ReadLine(); | |
} | |
static string JoinCarBrand(Car car, string aggregate) | |
{ | |
return String.Format("{0}, {1}", aggregate, car.Brand); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment