Skip to content

Instantly share code, notes, and snippets.

@ShawnMcCool
Created June 17, 2015 07:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ShawnMcCool/16cac102e06d02365403 to your computer and use it in GitHub Desktop.
Save ShawnMcCool/16cac102e06d02365403 to your computer and use it in GitHub Desktop.
A Sequence Collecton for C#
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