Created
June 20, 2014 15:48
-
-
Save lnicola/6bb76650d0a54b9b7155 to your computer and use it in GitHub Desktop.
Not really working LINQ GroupBy() implementation for sorted inputs
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; | |
using System.Linq; | |
using System.Text; | |
using System.Threading.Tasks; | |
namespace ConsoleApplication4 | |
{ | |
public class EnumeratorBox<T> | |
{ | |
public IEnumerator<T> Value { get; set; } | |
public bool IsCompleted { get; set; } | |
public EnumeratorBox(IEnumerator<T> value) | |
{ | |
Value = value; | |
} | |
} | |
public class AdjacentGrouping<TKey, TElement> : IGrouping<TKey, TElement> | |
{ | |
public TKey Key { get; private set; } | |
private IEnumerator<TElement> enumerator; | |
public AdjacentGrouping(TKey key, IEnumerator<TElement> enumerator) | |
{ | |
this.Key = key; | |
this.enumerator = enumerator; | |
} | |
public IEnumerator<TElement> GetEnumerator() | |
{ | |
return enumerator; | |
} | |
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() | |
{ | |
return enumerator; | |
} | |
} | |
public struct GroupAdjacentByEnumerator<TElement, TKey> : IEnumerator<TElement> | |
{ | |
private EnumeratorBox<TElement> enumeratorBox; | |
private Func<TElement, TKey> keySelector; | |
private TKey key; | |
private bool started; | |
public GroupAdjacentByEnumerator(EnumeratorBox<TElement> enumeratorBox, Func<TElement, TKey> keySelector, TKey key) | |
{ | |
this.enumeratorBox = enumeratorBox; | |
this.keySelector = keySelector; | |
this.key = key; | |
this.started = false; | |
} | |
public TElement Current | |
{ | |
get { return enumeratorBox.Value.Current; } | |
} | |
public void Dispose() | |
{ | |
} | |
object System.Collections.IEnumerator.Current | |
{ | |
get { return (enumeratorBox as System.Collections.IEnumerator).Current; } | |
} | |
public bool MoveNext() | |
{ | |
if (!started) | |
{ | |
started = true; | |
return true; | |
} | |
if (!enumeratorBox.Value.MoveNext()) | |
{ | |
enumeratorBox.IsCompleted = true; | |
return false; | |
} | |
var newKey = keySelector(enumeratorBox.Value.Current); | |
return Object.Equals(newKey, key); | |
} | |
public void Reset() | |
{ | |
throw new NotSupportedException(); | |
} | |
} | |
static class EnumerableExtensions | |
{ | |
public static IEnumerable<IGrouping<TKey, TElement>> GroupAdjacentBy<TElement, TKey>(this IEnumerable<TElement> source, Func<TElement, TKey> keySelector) | |
{ | |
var enumeratorBox = new EnumeratorBox<TElement>(source.GetEnumerator()); | |
if (!enumeratorBox.Value.MoveNext()) | |
{ | |
enumeratorBox.Value.Dispose(); | |
yield break; | |
} | |
do | |
{ | |
var key = keySelector(enumeratorBox.Value.Current); | |
yield return new AdjacentGrouping<TKey, TElement>(key, new GroupAdjacentByEnumerator<TElement, TKey>(enumeratorBox, keySelector, key)); | |
} while (!enumeratorBox.IsCompleted); | |
enumeratorBox.Value.Dispose(); | |
} | |
} | |
class Program | |
{ | |
static void Main() | |
{ | |
var foo = new[] { 1, 1, 1, 2, 2, 3 }; | |
foreach (var group in foo.GroupAdjacentBy(x => x)) | |
Console.WriteLine("{0}: {1}", group.Key, String.Join(" ", group)); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment