Created
June 17, 2015 07:52
-
-
Save ShawnMcCool/16cac102e06d02365403 to your computer and use it in GitHub Desktop.
A Sequence Collecton for C#
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.Collections.Generic; | |
using Infrastructure; | |
using NUnit.Framework; | |
namespace Collections { | |
[TestFixture] public class SeqTests { | |
[Test] | |
public void can_access_the_head() { | |
var seq = new Seq<DomainEvent>(); | |
var first = new TestEvent(); | |
var second = new TestEvent(); | |
var third = new TestEvent(); | |
seq.Add(first); | |
seq.Add(second); | |
seq.Add(third); | |
Assert.AreSame(first, seq.Head); | |
} | |
[Test] | |
public void can_access_the_tail() { | |
var seq = new Seq<DomainEvent>(); | |
var first = new TestEvent(); | |
var second = new TestEvent(); | |
var third = new TestEvent(); | |
seq.Add(first); | |
seq.Add(second); | |
seq.Add(third); | |
var tail = seq.Tail; | |
Assert.AreEqual(2, tail.Count); | |
Assert.AreEqual(second, tail[0]); | |
Assert.AreSame(third, tail[1]); | |
} | |
[Test] | |
public void can_access_values_with_array_accessor() { | |
var seq = new Seq<DomainEvent>(); | |
var domainEvent = new TestEvent(); | |
seq.Add(domainEvent); | |
Assert.AreSame(domainEvent, seq[0]); | |
} | |
[Test] | |
public void can_add_items_with_literal_syntax() { | |
var seq = new Seq<DomainEvent> {new TestEvent(), new TestEvent()}; | |
Assert.AreEqual(2, seq.Count); | |
} | |
[Test] | |
public void can_add_multiple_items() { | |
var seq = new Seq<DomainEvent>(); | |
var first = new TestEvent(); | |
var second = new TestEvent(); | |
var third = new TestEvent(); | |
seq.Add(new List<DomainEvent> {first, second, third}); | |
Assert.AreSame(first, seq[0]); | |
Assert.AreSame(second, seq[1]); | |
Assert.AreSame(third, seq[2]); | |
} | |
[Test] | |
public void can_create_a_sequence() { | |
Assert.IsInstanceOf<Seq<DomainEvent>>(new Seq<DomainEvent>()); | |
Assert.IsInstanceOf<Seq<TestEvent>>(new Seq<TestEvent>()); | |
} | |
[Test] | |
public void can_get_a_count_of_items_in_the_sequence() { | |
var seq = new Seq<DomainEvent>(); | |
seq.Add(new TestEvent()); | |
Assert.AreEqual(1, seq.Count); | |
seq.Add(new TestEvent()); | |
Assert.AreEqual(2, seq.Count); | |
} | |
[Test] | |
public void can_iterate_over_items() { | |
var seq = new Seq<DomainEvent> {new TestEvent(), new TestEvent()}; | |
var i = 0; | |
foreach (var e in seq) { | |
i++; | |
} | |
Assert.AreEqual(2, i); | |
} | |
[Test] | |
public void items_retain_search_order_when_adding() { | |
var seq = new Seq<DomainEvent>(); | |
var first = new TestEvent(); | |
var second = new TestEvent(); | |
var third = new TestEvent(); | |
seq.Add(new List<DomainEvent> {first, second, third}); | |
seq.Add(new List<DomainEvent> {third, second, first}); | |
Assert.AreSame(first, seq[0]); | |
Assert.AreSame(second, seq[1]); | |
Assert.AreSame(third, seq[2]); | |
Assert.AreSame(third, seq[3]); | |
Assert.AreSame(second, seq[4]); | |
Assert.AreSame(first, seq[5]); | |
} | |
} | |
} | |
using System.Collections; | |
using System.Collections.Generic; | |
using System.Linq; | |
namespace Collections { | |
public class Seq<T> : IEnumerable<T> { | |
private Dictionary<int, T> items; | |
public Seq() { | |
items = new Dictionary<int, T>(); | |
} | |
public Seq(Dictionary<int, T> items) { | |
this.items = items; | |
} | |
public int Count { | |
get { return items.Count; } | |
} | |
public T this[int index] { | |
get { return items[index]; } | |
set { SetValueAtIndex(index, value); } | |
} | |
public T Head { | |
get { return items[0]; } | |
} | |
public Seq<T> Tail { | |
get { | |
if (items.Count < 2) { | |
return new Seq<T>(); | |
} | |
return BuildSeq(items.Skip(1).ToDictionary(t => t.Key, t => t.Value)); | |
} | |
} | |
public IEnumerator<T> GetEnumerator() { | |
return items.Values.ToList().GetEnumerator(); | |
} | |
IEnumerator IEnumerable.GetEnumerator() { | |
return GetEnumerator(); | |
} | |
public void Add(T t) { | |
items[items.Count] = t; | |
items = Sort(items); | |
} | |
public void Add(IEnumerable<T> newItems) { | |
foreach (var item in newItems) { | |
Add(item); | |
} | |
} | |
private void SetValueAtIndex(int index, T value) { | |
items[index] = value; | |
items = Sort(items); | |
} | |
private Seq<T> BuildSeq(Dictionary<int, T> items) { | |
return new Seq<T>(Sort(items)); | |
} | |
private static Dictionary<int, T> Sort(Dictionary<int, T> items) { | |
var newDictionary = new Dictionary<int, T>(); | |
var sortedItems = items.OrderBy(i => i.Key).ToDictionary(t => t.Key, t => t.Value); | |
foreach (var i in Enumerable.Range(0, sortedItems.Count)) { | |
newDictionary[i] = sortedItems.Skip(i).First().Value; | |
} | |
return newDictionary; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment