Reputation: 2754
I'm wondering how can I change way in which SortedSet determines whether two objects are equal.
I have SortedSet<Tuple<Edge, int>>(new Helpers.EdgeDistanceComparer())
and Comparer method is:
public class EdgeDistanceComparer : IComparer<Tuple<Edge,int>>
{
public int Compare(Tuple<Edge, int> x, Tuple<Edge, int> y)
{
return Comparer.Default.Compare(x.Item2, y.Item2);
}
}
I believe because of this Sorted set compares only integers (Tuple.Item2), how can I do comparison on Edge class
EDIT
To explain question more:
I want to compare items by Edge class, and to sort them by Tuple.Item2, and if two Tuple.Item2 are equal, I want to add that item to SortedSet, nevertheless.
EDIT 2
Ben Gave good answer but in the end I've decided to add one more property to my class so that value I kept in Tuple.Item2 is now being saved inside property of my Edge class. And then I implemented IComparable interface, so here is how my Edge class looks like:
public class Edge : IComparable
{
public Coordinate Coordinates { get; set; }
public string Value { get; set; }
public Edge Parent { get; set; }
public int Cost { get; set; }
public int CompareTo(object obj)
{
var thatEdge = (Edge) obj;
if (Cost > thatEdge.Cost)
{
return 1;
}
if (Cost < thatEdge.Cost)
{
return -1;
}
// cost may be same but coordinates must be different
if (Cost == thatEdge.Cost &&
(Coordinates.X != thatEdge.Coordinates.X || Coordinates.Y != thatEdge.Coordinates.Y))
{
return -1;
}
return 0;
}
}
And IComparer for SortedSet:
public class EdgeDistanceComparer : IComparer<Edge>
{
public int Compare(Edge x, Edge y)
{
return Comparer.Default.Compare(x, y);
}
}
Upvotes: 3
Views: 1609
Reputation: 6975
I believe this answer to another question contains the closest thing you'll get to what you want
In this case the TValue
is your Tuple<Edge,int>
, so your IComparer
that's passed in on construction would be the same as the one in your post.
The only other addition, to make it behave like a Set
, is to add a check to the Add
method to only add to the collection if the collection does not already contain an item with the same Edge
. One way to do that would be:
public void Add(TValue item)
{
if(!_Container.Select(p => p.Value).Contains(item, _equalityComparer)
_Container.Add(Indexed.Create(_Index++, item));
}
Where _equalityComparer
is an IEqualityComparer<Tuple<Edge,int>>
which returns true if the Edges are equal.
This is a bit of a mess unfortunately, and I think it probably loses a lot of performance benefits you probably want from the SortedSet
, but it may be the best you can get, since there's nothing in System.Collections
geared towards this. If performance isn't important, you could just try a Set
or even List
, and just sort when you need to. Even if performance is important, you might still want to do a comparison and see if this is even much better.
Upvotes: 3