You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
236 lines
9.3 KiB
236 lines
9.3 KiB
5 years ago
|
#if FAT
|
||
|
|
||
|
using System;
|
||
|
using System.Collections.Generic;
|
||
|
using System.Linq;
|
||
|
using LinqInternal.Collections.Specialized;
|
||
|
|
||
|
namespace LinqInternal.Collections
|
||
|
{
|
||
|
internal static partial class Extensions
|
||
|
{
|
||
|
public static IEnumerable<IGrouping<TKey, TSource>> GroupProgressiveBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
|
||
|
{
|
||
|
return GroupProgressiveBy(source, keySelector, null);
|
||
|
}
|
||
|
|
||
|
public static IEnumerable<IGrouping<TKey, TSource>> GroupProgressiveBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
|
||
|
{
|
||
|
if (source == null)
|
||
|
{
|
||
|
throw new ArgumentNullException("source");
|
||
|
}
|
||
|
if (keySelector == null)
|
||
|
{
|
||
|
throw new ArgumentNullException("keySelector");
|
||
|
}
|
||
|
return CreateGroupByIterator(source, keySelector, comparer);
|
||
|
}
|
||
|
|
||
|
public static IEnumerable<IGrouping<TKey, TElement>> GroupProgressiveBy<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector)
|
||
|
{
|
||
|
return GroupProgressiveBy(source, keySelector, elementSelector, null);
|
||
|
}
|
||
|
|
||
|
public static IEnumerable<IGrouping<TKey, TElement>> GroupProgressiveBy<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> resultSelector, IEqualityComparer<TKey> comparer)
|
||
|
{
|
||
|
if (source == null)
|
||
|
{
|
||
|
throw new ArgumentNullException("source");
|
||
|
}
|
||
|
if (keySelector == null)
|
||
|
{
|
||
|
throw new ArgumentNullException("keySelector");
|
||
|
}
|
||
|
if (resultSelector == null)
|
||
|
{
|
||
|
throw new ArgumentNullException("resultSelector");
|
||
|
}
|
||
|
return CreateGroupByIterator(source, keySelector, resultSelector, comparer);
|
||
|
}
|
||
|
|
||
|
public static IEnumerable<TResult> GroupProgressiveBy<TSource, TKey, TElement, TResult>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, Func<TKey, IEnumerable<TElement>, TResult> resultSelector)
|
||
|
{
|
||
|
return GroupProgressiveBy(source, keySelector, elementSelector, resultSelector, null);
|
||
|
}
|
||
|
|
||
|
public static IEnumerable<TResult> GroupProgressiveBy<TSource, TKey, TElement, TResult>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, Func<TKey, IEnumerable<TElement>, TResult> resultSelector, IEqualityComparer<TKey> comparer)
|
||
|
{
|
||
|
if (source == null)
|
||
|
{
|
||
|
throw new ArgumentNullException("source");
|
||
|
}
|
||
|
if (keySelector == null)
|
||
|
{
|
||
|
throw new ArgumentNullException("keySelector");
|
||
|
}
|
||
|
if (elementSelector == null)
|
||
|
{
|
||
|
throw new ArgumentNullException("elementSelector");
|
||
|
}
|
||
|
if (resultSelector == null)
|
||
|
{
|
||
|
throw new ArgumentNullException("resultSelector");
|
||
|
}
|
||
|
return CreateGroupByIterator(source, keySelector, elementSelector, resultSelector, comparer);
|
||
|
}
|
||
|
|
||
|
public static IEnumerable<TResult> GroupProgressiveBy<TSource, TKey, TResult>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TKey, IEnumerable<TSource>, TResult> resultSelector)
|
||
|
{
|
||
|
return GroupProgressiveBy(source, keySelector, resultSelector, null);
|
||
|
}
|
||
|
|
||
|
public static IEnumerable<TResult> GroupProgressiveBy<TSource, TKey, TResult>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TKey, IEnumerable<TSource>, TResult> resultSelector, IEqualityComparer<TKey> comparer)
|
||
|
{
|
||
|
if (source == null)
|
||
|
{
|
||
|
throw new ArgumentNullException("source");
|
||
|
}
|
||
|
if (keySelector == null)
|
||
|
{
|
||
|
throw new ArgumentNullException("keySelector");
|
||
|
}
|
||
|
if (resultSelector == null)
|
||
|
{
|
||
|
throw new ArgumentNullException("resultSelector");
|
||
|
}
|
||
|
return CreateGroupByIterator(source, keySelector, resultSelector, comparer);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal static partial class Extensions
|
||
|
{
|
||
|
//GroupBy progressive implementation
|
||
|
|
||
|
private static IEnumerable<IGrouping<TKey, TSource>> CreateGroupByIterator<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
|
||
|
{
|
||
|
// NOTICE this method has no null check
|
||
|
var groups = new Dictionary<TKey, List<TSource>>(comparer);
|
||
|
var nullList = new List<TSource>();
|
||
|
var counter = 0;
|
||
|
var nullCounter = -1;
|
||
|
|
||
|
foreach (TSource element in source)
|
||
|
{
|
||
|
var key = keySelector(element);
|
||
|
if (ReferenceEquals(key, null))
|
||
|
{
|
||
|
nullList.Add(element);
|
||
|
if (nullCounter == -1)
|
||
|
{
|
||
|
nullCounter = counter;
|
||
|
counter++;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
List<TSource> group;
|
||
|
if (!groups.TryGetValue(key, out group))
|
||
|
{
|
||
|
group = new List<TSource>();
|
||
|
groups.Add(key, group);
|
||
|
counter++;
|
||
|
}
|
||
|
group.Add(element);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
counter = 0;
|
||
|
foreach (var group in groups)
|
||
|
{
|
||
|
if (counter == nullCounter)
|
||
|
{
|
||
|
yield return new Grouping<TKey, TSource>(default(TKey), nullList);
|
||
|
counter++;
|
||
|
}
|
||
|
|
||
|
yield return new Grouping<TKey, TSource>(group.Key, group.Value);
|
||
|
counter++;
|
||
|
}
|
||
|
|
||
|
if (counter == nullCounter)
|
||
|
{
|
||
|
yield return new Grouping<TKey, TSource>(default(TKey), nullList);
|
||
|
// counter++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private static IEnumerable<IGrouping<TKey, TElement>> CreateGroupByIterator<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer)
|
||
|
{
|
||
|
// NOTICE this method has no null check
|
||
|
var groups = new Dictionary<TKey, List<TElement>>(comparer);
|
||
|
var nullList = new List<TElement>();
|
||
|
var counter = 0;
|
||
|
var nullCounter = -1;
|
||
|
|
||
|
foreach (TSource item in source)
|
||
|
{
|
||
|
var key = keySelector(item);
|
||
|
var element = elementSelector(item);
|
||
|
if (ReferenceEquals(key, null))
|
||
|
{
|
||
|
nullList.Add(element);
|
||
|
if (nullCounter == -1)
|
||
|
{
|
||
|
nullCounter = counter;
|
||
|
counter++;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
List<TElement> group;
|
||
|
if (!groups.TryGetValue(key, out group))
|
||
|
{
|
||
|
group = new List<TElement>();
|
||
|
groups.Add(key, group);
|
||
|
counter++;
|
||
|
}
|
||
|
group.Add(element);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
counter = 0;
|
||
|
foreach (var group in groups)
|
||
|
{
|
||
|
if (counter == nullCounter)
|
||
|
{
|
||
|
yield return new Grouping<TKey, TElement>(default(TKey), nullList);
|
||
|
counter++;
|
||
|
}
|
||
|
|
||
|
yield return new Grouping<TKey, TElement>(group.Key, group.Value);
|
||
|
counter++;
|
||
|
}
|
||
|
|
||
|
if (counter == nullCounter)
|
||
|
{
|
||
|
yield return new Grouping<TKey, TElement>(default(TKey), nullList);
|
||
|
// counter++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private static IEnumerable<TResult> CreateGroupByIterator<TSource, TKey, TElement, TResult>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, Func<TKey, IEnumerable<TElement>, TResult> resultSelector, IEqualityComparer<TKey> comparer)
|
||
|
{
|
||
|
// NOTICE this method has no null check
|
||
|
var groups = GroupProgressiveBy(source, keySelector, elementSelector, comparer);
|
||
|
|
||
|
foreach (IGrouping<TKey, TElement> group in groups)
|
||
|
{
|
||
|
yield return resultSelector(group.Key, group);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private static IEnumerable<TResult> CreateGroupByIterator<TSource, TKey, TResult>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TKey, IEnumerable<TSource>, TResult> resultSelector, IEqualityComparer<TKey> comparer)
|
||
|
{
|
||
|
// NOTICE this method has no null check
|
||
|
var groups = GroupProgressiveBy(source, keySelector, comparer);
|
||
|
|
||
|
foreach (IGrouping<TKey, TSource> group in groups)
|
||
|
{
|
||
|
yield return resultSelector(group.Key, group);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#endif
|