Skip to content

Instantly share code, notes, and snippets.

@lnicola
Created June 20, 2014 15:48
Show Gist options
  • Save lnicola/6bb76650d0a54b9b7155 to your computer and use it in GitHub Desktop.
Save lnicola/6bb76650d0a54b9b7155 to your computer and use it in GitHub Desktop.
Not really working LINQ GroupBy() implementation for sorted inputs
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