C# Sortable collection which allows duplicate keys

前端 未结 16 2158
旧巷少年郎
旧巷少年郎 2020-11-28 10:06

I am writing a program to set a sequence in which various objects will appear in report. The sequence is the Y position (cell) on Excel spreadsheet.

A demo part of co

16条回答
  •  孤独总比滥情好
    2020-11-28 11:01

    The trick is to augment your object with a unique key. See the following test which passes. I want to keep my points sorted by their X value. Just using a naked Point2D in my comparison function will cause points with the same X value to be eliminated. So I wrap the Point2D in a tagging class called Indexed.

    [Fact]
    public void ShouldBeAbleToUseCustomComparatorWithSortedSet()
    {
        // Create comparer that compares on X value but when X
        // X values are uses the index
        var comparer = new 
            System.Linq.Comparer>(( p0, p1 ) =>
            {
                var r = p0.Value.X.CompareTo(p1.Value.X);
                return r == 0 ? p0.Index.CompareTo(p1.Index) : r;
            });
    
        // Sort points according to X
        var set = new SortedSet>(comparer);
    
        int i=0;
    
        // Create a helper function to wrap each point in a unique index
        Action index = p =>
        {
            var ip = Indexed.Create(i++, p);
            set.Add(ip);
        };
    
        index(new Point2D(9,10));
        index(new Point2D(1,25));
        index(new Point2D(11,-10));
        index(new Point2D(2,99));
        index(new Point2D(5,55));
        index(new Point2D(5,23));
        index(new Point2D(11,11));
        index(new Point2D(21,12));
        index(new Point2D(-1,76));
        index(new Point2D(16,21));
        set.Count.Should()
           .Be(10);
        var xs = set.Select(p=>p.Value.X).ToList();
        xs.Should()
          .BeInAscendingOrder();
        xs.ShouldBeEquivalentTo(new[]{-1,1,2,5,5,9,11,11,16,21});
    
    }
    

    Utilities to make this work are

    A comparer that takes a lambda

    public class Comparer : IComparer
    {
        private readonly Func _comparer;
    
        public Comparer(Func comparer)
        {
            if (comparer == null)
                throw new ArgumentNullException("comparer");
            _comparer = comparer;
        }
    
        public int Compare(T x, T y)
        {
            return _comparer(x, y);
        }
    }
    

    A tagging struct

    public struct Indexed
    {
        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 Create(int indexed, T value)
        {
            return new Indexed(indexed, value);
        }
    }
    

提交回复
热议问题