Kelas koleksi ini akan mempertahankan duplikat dan menyisipkan tata urutan untuk duplikat. Triknya adalah memberi tag item dengan nilai unik saat disisipkan untuk menjaga tata urutan yang stabil. Kemudian kami membungkus semuanya dalam antarmuka ICollection.
public class SuperSortedSet<TValue> : ICollection<TValue>
{
private readonly SortedSet<Indexed<TValue>> _Container;
private int _Index = 0;
private IComparer<TValue> _Comparer;
public SuperSortedSet(IComparer<TValue> comparer)
{
_Comparer = comparer;
var c2 = new System.Linq.Comparer<Indexed<TValue>>((p0, p1) =>
{
var r = _Comparer.Compare(p0.Value, p1.Value);
if (r == 0)
{
if (p0.Index == -1
|| p1.Index == -1)
return 0;
return p0.Index.CompareTo(p1.Index);
}
else return r;
});
_Container = new SortedSet<Indexed<TValue>>(c2);
}
public IEnumerator<TValue> GetEnumerator() { return _Container.Select(p => p.Value).GetEnumerator(); }
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
public void Add(TValue item) { _Container.Add(Indexed.Create(_Index++, item)); }
public void Clear() { _Container.Clear();}
public bool Contains(TValue item) { return _Container.Contains(Indexed.Create(-1,item)); }
public void CopyTo(TValue[] array, int arrayIndex)
{
foreach (var value in this)
{
if (arrayIndex >= array.Length)
{
throw new ArgumentException("Not enough space in array");
}
array[arrayIndex] = value;
arrayIndex++;
}
}
public bool Remove(TValue item) { return _Container.Remove(Indexed.Create(-1, item)); }
public int Count {
get { return _Container.Count; }
}
public bool IsReadOnly {
get { return false; }
}
}
kelas tes
[Fact]
public void ShouldWorkWithSuperSortedSet()
{
// Sort points according to X
var set = new SuperSortedSet<Point2D>
(new System.Linq.Comparer<Point2D>((p0, p1) => p0.X.CompareTo(p1.X)));
set.Add(new Point2D(9,10));
set.Add(new Point2D(1,25));
set.Add(new Point2D(11,-10));
set.Add(new Point2D(2,99));
set.Add(new Point2D(5,55));
set.Add(new Point2D(5,23));
set.Add(new Point2D(11,11));
set.Add(new Point2D(21,12));
set.Add(new Point2D(-1,76));
set.Add(new Point2D(16,21));
var xs = set.Select(p=>p.X).ToList();
xs.Should().BeInAscendingOrder();
xs.Count.Should()
.Be(10);
xs.ShouldBeEquivalentTo(new[]{-1,1,2,5,5,9,11,11,16,21});
set.Remove(new Point2D(5,55));
xs = set.Select(p=>p.X).ToList();
xs.Count.Should()
.Be(9);
xs.ShouldBeEquivalentTo(new[]{-1,1,2,5,9,11,11,16,21});
set.Remove(new Point2D(5,23));
xs = set.Select(p=>p.X).ToList();
xs.Count.Should()
.Be(8);
xs.ShouldBeEquivalentTo(new[]{-1,1,2,9,11,11,16,21});
set.Contains(new Point2D(11, 11))
.Should()
.BeTrue();
set.Contains(new Point2D(-1, 76))
.Should().BeTrue();
// Note that the custom compartor function ignores the Y value
set.Contains(new Point2D(-1, 66))
.Should().BeTrue();
set.Contains(new Point2D(27, 66))
.Should().BeFalse();
}
Struktur pemberian tag
public struct Indexed<T>
{
public int Index { get; private set; }
public T Value { get; private set; }
public Indexed(int index, T value) : this()
{
Index = index;
Value = value;
}
public override string ToString()
{
return "(Indexed: " + Index + ", " + Value.ToString () + " )";
}
}
public class Indexed
{
public static Indexed<T> Create<T>(int indexed, T value)
{
return new Indexed<T>(indexed, value);
}
}
Pembantu pembanding lambda
public class Comparer<T> : IComparer<T>
{
private readonly Func<T, T, int> _comparer;
public Comparer(Func<T, T, int> comparer)
{
if (comparer == null)
throw new ArgumentNullException("comparer");
_comparer = comparer;
}
public int Compare(T x, T y)
{
return _comparer(x, y);
}
}